Last active
October 23, 2020 19:51
-
-
Save raylee/8aa3cc04d60d728eefdbce51f2b9f9ee to your computer and use it in GitHub Desktop.
guesses passwords for zip files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
// zipguess.go | |
// reads a tsv file, one set of possibilities per line | |
// one possibile segment is chosen from each line in order | |
// and concatenated together into a guess | |
import ( | |
"flag" | |
"fmt" | |
"io/ioutil" | |
"os" | |
"strings" | |
ezip "github.com/olegpolukhin/zip" | |
) | |
type Guesser struct { | |
atoms [][]string | |
} | |
func NewGuesses(filename string) (*Guesser, error) { | |
c, err := ioutil.ReadFile(filename) | |
if err != nil { | |
return nil, err | |
} | |
g := Guesser{make([][]string, 0)} | |
for _, line := range strings.Split(string(c), "\n") { | |
atoms := strings.FieldsFunc(line, func(r rune) bool { | |
if r == '\t' { | |
return true | |
} else { | |
return false | |
} | |
}) | |
if len(atoms) > 0 { | |
g.atoms = append(g.atoms, atoms) | |
} | |
} | |
return &g, nil | |
} | |
func Inc(indices, boundaries []int) (more bool) { | |
// if a complete rollover, all values back to zero, then return false, otherwise true | |
for i := len(indices) - 1; i >= 0; i-- { | |
indices[i]++ | |
if indices[i] == boundaries[i] { | |
indices[i] = 0 | |
} else { | |
return true | |
} | |
} | |
return false | |
} | |
func (g *Guesser) Guesses(root int) <-chan string { | |
results := make(chan string, 1000) | |
indicies := make([]int, len(g.atoms)) | |
boundaries := make([]int, len(g.atoms)) | |
base := 0 | |
if root >= 0 { | |
indicies[0] = root | |
base = 1 | |
} | |
for i := 0; i < len(boundaries); i++ { | |
boundaries[i] = len(g.atoms[i]) | |
} | |
gen := func(g *Guesser) { | |
for Inc(indicies[base:], boundaries[base:]) { | |
var guess string | |
for i := 0; i < len(indicies); i++ { | |
guess += g.atoms[i][indicies[i]] | |
} | |
results <- guess | |
} | |
close(results) | |
} | |
go gen(g) | |
return results | |
} | |
func (g *Guesser) String() string { | |
var s string | |
for i := 0; i < len(g.atoms); i++ { | |
s += fmt.Sprintf("atom %2d: %s\n", i, g.atoms[i]) | |
} | |
return s | |
} | |
var ( | |
atomfile = flag.String("atoms", "", "a tab-separated-value file containing the atoms used in a guess. One atom is selected from each row and concatenated together.") | |
zipfile = flag.String("zip", "", "filename of the zip file to guess at") | |
) | |
func Usage() string { | |
return `Usage: | |
zipguess -atoms <atomfile.tsv> -zip <zipfile.zip> | |
<atomfile.tsv> is a tab-separated value (TSV) file. Each row is | |
used as a set of guesses for that position. One guess is taken from | |
each row in order, and concatenated into a password to attempt | |
against <zipfile.zip>. It's assumed all files contained in the zip | |
use the same password. Only the first password for the first | |
password protected file is returned. | |
` | |
} | |
func main() { | |
flag.Parse() | |
if *atomfile == "" || *zipfile == "" { | |
fmt.Println(Usage()) | |
os.Exit(1) | |
} | |
g, err := NewGuesses(*atomfile) | |
if err != nil { | |
fmt.Println("atomfile error:", err) | |
os.Exit(1) | |
} | |
fmt.Printf("Atoms in use:\n%s", g) | |
checkPasswords(g) | |
} | |
func checkPasswords(g *Guesser) string { | |
r, err := ezip.OpenReader(*zipfile) | |
if err != nil { | |
fmt.Printf("Could not open %s: %v", *zipfile, err) | |
return "" | |
} | |
defer r.Close() | |
if len(r.File) < 1 { | |
fmt.Printf("Zip file contains no files?") | |
return "" | |
} | |
f := r.File[0] | |
if !f.IsEncrypted() { | |
fmt.Printf("Files are not encrypted: %s", f.Name) | |
return "" | |
} | |
for guess := range g.Guesses(-1) { | |
f.SetPassword(guess) | |
rc, err := f.Open() | |
if err != nil { | |
fmt.Println(err) | |
continue | |
} | |
_, err = ioutil.ReadAll(rc) | |
rc.Close() | |
if err != nil { | |
continue | |
} | |
fmt.Println("Success:", guess) | |
return guess | |
} | |
return "" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment