diff --git a/axml2xml/main.go b/axml2xml/main.go index 142fc8a..d810065 100644 --- a/axml2xml/main.go +++ b/axml2xml/main.go @@ -1,20 +1,28 @@ package main import ( + "apkverifier" + "binxml" + "crypto/sha1" + "crypto/sha256" + "crypto/x509/pkix" + "encoding/hex" "encoding/xml" "flag" "fmt" "io" "os" - - "binxml" + "reflect" + "shared" "strings" + "time" ) func main() { isApk := flag.Bool("a", false, "The input file is an apk (default if INPUT is *.apk)") isManifest := flag.Bool("m", false, "The input file is an AndroidManifest.xml (default)") isResources := flag.Bool("r", false, "The input is resources.arsc file (default if INPUT is *.arsc)") + verifyApk := flag.Bool("v", false, "Verify the file if it is an APK.") flag.Parse() @@ -37,7 +45,7 @@ func main() { } if *isApk { - processApk(input) + processApk(input, *verifyApk) } else { if input == "-" { r = os.Stdin @@ -69,54 +77,73 @@ func main() { } } -func processApk(input string) { - zr, err := binxml.OpenZip(input) +func processApk(input string, verify bool) { + enc := xml.NewEncoder(os.Stdout) + enc.Indent("", " ") + + parser, err := shared.NewApkParser(0, input, enc) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } - defer zr.Close() - - var res *binxml.ResourceTable + defer parser.Close() - zrf := zr.File["resources.arsc"] - if zrf == nil { - fmt.Fprintln(os.Stderr, input, "Failed to find resources.arsc") - } else { - if err := zrf.Open(); err != nil { - fmt.Fprintln(os.Stderr, input, err) - } else { - defer zrf.Close() - - zrf.Next() - res, err = binxml.ParseResourceTable(zrf) - if err != nil { - fmt.Fprintln(os.Stderr, input, err) - } - } + _, err = parser.ParseManifest() + fmt.Println() + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) } - zrf = zr.File["AndroidManifest.xml"] - if zrf == nil { - fmt.Fprintln(os.Stderr, "Failed to find manifest") - os.Exit(1) + if !verify { + return } - if err := zrf.Open(); err != nil { + fmt.Print("\n=====================================\n") + + res, err := apkverifier.Verify(input, parser.Zip()) + if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } - defer zrf.Close() - zrf.Next() + fmt.Println("Uses V2 signing scheme:", res.UsingSchemeV2) + for _, certs := range res.SignerCerts { + for _, cert := range certs { + thumb1 := sha1.Sum(cert.Raw) + thumb256 := sha256.Sum256(cert.Raw) + fmt.Print("\nSubject\n") + printCertName(cert.Subject) + fmt.Println("validfrom:", cert.NotBefore.Format(time.RFC3339)) + fmt.Println("validto:", cert.NotAfter.Format(time.RFC3339)) + fmt.Println("serialnumber:", cert.SerialNumber.Text(16)) + fmt.Println("thumbprint:", hex.EncodeToString(thumb1[:])) + fmt.Println("thumbprint256:", hex.EncodeToString(thumb256[:])) + fmt.Println("Issuer") + printCertName(cert.Issuer) + } + } +} - enc := xml.NewEncoder(os.Stdout) - enc.Indent("", " ") +func printCertName(n pkix.Name) { + v := reflect.ValueOf(n) + t := reflect.TypeOf(n) + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + if f.PkgPath != "" { + continue + } + + switch val := v.Field(i).Interface().(type) { + case string: + if len(val) != 0 { + fmt.Printf(" %s: %s\n", f.Name, val) + } + case []string: + if len(val) != 0 { + fmt.Printf(" %s: %s\n", f.Name, strings.Join(val, ";")) + } + } - err = binxml.ParseManifest(zrf, enc, res) - fmt.Println() - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) } } diff --git a/zipreader.go b/zipreader.go index a8ccd5d..d03de77 100644 --- a/zipreader.go +++ b/zipreader.go @@ -4,10 +4,11 @@ import ( "archive/zip" "compress/flate" "encoding/binary" + "errors" "fmt" "io" "os" - "path/filepath" + "path" ) type zipReaderFileSubEntry struct { @@ -16,7 +17,8 @@ type zipReaderFileSubEntry struct { } type ZipReaderFile struct { - Name string + Name string + IsDir bool zipFile *os.File internalReader io.ReadCloser @@ -34,8 +36,13 @@ type ZipReader struct { } func (zr *ZipReaderFile) Open() error { + if zr.internalReader != nil { + return errors.New("File is already opened.") + } + if zr.zipEntry != nil { var err error + zr.curEntry = 0 zr.internalReader, err = zr.zipEntry.Open() return err } else { @@ -114,8 +121,8 @@ func (zr *ZipReader) Close() error { return err } -func OpenZip(path string) (zr *ZipReader, err error) { - f, err := os.Open(path) +func OpenZip(zippath string) (zr *ZipReader, err error) { + f, err := os.Open(zippath) if err != nil { return } @@ -135,10 +142,11 @@ func OpenZip(path string) (zr *ZipReader, err error) { zipinfo, err = tryReadZip(f) if err == nil { for _, zf := range zipinfo.File { - cl := filepath.Clean(zf.Name) + cl := path.Clean(zf.Name) if zr.File[cl] == nil { zr.File[cl] = &ZipReaderFile{ Name: cl, + IsDir: zf.FileInfo().IsDir(), zipFile: f, zipEntry: zf, } @@ -177,7 +185,7 @@ func OpenZip(path string) (zr *ZipReader, err error) { return } - fileName := filepath.Clean(string(buf)) + fileName := path.Clean(string(buf)) fileOffset := off + 30 + int64(nameLen) + int64(extraLen) zrf := zr.File[fileName]