Skip to content

Commit

Permalink
Implement apk verification
Browse files Browse the repository at this point in the history
  • Loading branch information
Vojtech Bocek committed Mar 8, 2017
1 parent d98652a commit d93c6bd
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 43 deletions.
101 changes: 64 additions & 37 deletions axml2xml/main.go
Original file line number Diff line number Diff line change
@@ -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()

Expand All @@ -37,7 +45,7 @@ func main() {
}

if *isApk {
processApk(input)
processApk(input, *verifyApk)
} else {
if input == "-" {
r = os.Stdin
Expand Down Expand Up @@ -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)
}
}
20 changes: 14 additions & 6 deletions zipreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"archive/zip"
"compress/flate"
"encoding/binary"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"path"
)

type zipReaderFileSubEntry struct {
Expand All @@ -16,7 +17,8 @@ type zipReaderFileSubEntry struct {
}

type ZipReaderFile struct {
Name string
Name string
IsDir bool

zipFile *os.File
internalReader io.ReadCloser
Expand All @@ -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 {
Expand Down Expand Up @@ -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
}
Expand All @@ -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,
}
Expand Down Expand Up @@ -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]
Expand Down

0 comments on commit d93c6bd

Please sign in to comment.