apkparser

package module
v0.0.0-...-25d3a81 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 26, 2023 License: LGPL-3.0 Imports: 21 Imported by: 0

README

apkparser

GoDoc Build Status

APK AndroidManifest.xml and resources.arsc parsing.

Works with Go 1.9 or higher.

Documentation on GoDoc

go get github.com/v4n0v/apkparser

ZipReader

Because Android can handle even broken ZIP archives, this packages has it's own zip reader, based on archive/zip.

axml2xml

A tool to extract AndroidManifest.xml and verify APK signature is also part of this repo.

go get github.com/v4n0v/apkparser
go install github.com/v4n0v/apkparser/axml2xml
./axml2xml -v application.apk

Example

package main

import (
	"fmt"
	"github.com/v4n0v/apkparser"
	"os"
)

func main() {
	apkInfo, err := apkparser.ParseApk(os.Args[1])
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open the APK: %s", err)
		os.Exit(1)
		return
	}
	fmt.Println(apkInfo)
}

Documentation

Overview

Package apkparser parses AndroidManifest.xml and resources.arsc from Android APKs.

Example
package main

import (
	"fmt"
	"github.com/v4n0v/apkparser"
	"os"
)

func main() {
	apkInfo, err := apkparser.ParseApk(os.Args[1])
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open the APK: %s", err)
		os.Exit(1)
		return
	}
	fmt.Println(apkInfo)
}
Output:

Index

Examples

Constants

View Source
const (
	AttrTypeNull          AttrType = 0x00
	AttrTypeReference              = 0x01
	AttrTypeAttribute              = 0x02
	AttrTypeString                 = 0x03
	AttrTypeFloat                  = 0x04
	AttrTypeIntDec                 = 0x10
	AttrTypeIntHex                 = 0x11
	AttrTypeIntBool                = 0x12
	AttrTypeIntColorArgb8          = 0x1c
	AttrTypeIntColorRgb8           = 0x1d
	AttrTypeIntColorArgb4          = 0x1e
	AttrTypeIntColorRgb4           = 0x1f
)

Variables

View Source
var ErrEndParsing = errors.New("end manifest parsing")

Return this error from EncodeToken to tell apkparser to finish parsing, to be used when you found the value you care about and don't need the rest.

View Source
var ErrPlainTextManifest = errors.New("xml is in plaintext, binary form expected")

Some samples have manifest in plaintext, this is an error. 2c882a2376034ed401be082a42a21f0ac837689e7d3ab6be0afb82f44ca0b859

View Source
var ErrUnknownResourceDataType = errors.New("Unknown resource data type")

Functions

func ParseManifest deprecated

func ParseManifest(r io.Reader, enc ManifestEncoder, resources *ResourceTable) error

Deprecated: just calls ParseXML

func ParseXml

func ParseXml(r io.Reader, enc ManifestEncoder, resources *ResourceTable) error

Parse the binary Xml format. The resources are optional and can be nil.

Types

type ApkInfo

type ApkInfo struct {
	Package     string
	VersionName string
	VersionCode int32
	Label       string
	Icon        IconData
}

func ParseApk

func ParseApk(path string) (ApkInfo, error)

Calls ParseApkReader

func ParseApkReader

func ParseApkReader(r io.ReadSeeker) (ApkInfo, error)

Parse APK's Manifest, including resolving refences to resource values. encoder expects an XML encoder instance, like Encoder from encoding/xml package.

zipErr != nil means the APK couldn't be opened. The manifest will be parsed even when resourcesErr != nil, just without reference resolving.

func ParseApkWithZip

func ParseApkWithZip(zip *ZipReader) (ApkInfo, error)

Parse APK's Manifest, including resolving refences to resource values. encoder expects an XML encoder instance, like Encoder from encoding/xml package.

Use this if you already opened the zip with OpenZip or OpenZipReader before. This method will not Close() the zip.

The manifest will be parsed even when resourcesErr != nil, just without reference resolving.

type ApkParser

type ApkParser struct {
	// contains filtered or unexported fields
}

func NewParser

func NewParser(zip *ZipReader, encoder ManifestEncoder) (parser *ApkParser, resourcesErr error)

Prepare the ApkParser instance, load resources if possible. encoder expects an XML encoder instance, like Encoder from encoding/xml package.

This method will not Close() the zip, you are still the owner.

func (*ApkParser) ParseIcon

func (p *ApkParser) ParseIcon(name string) (imageBase64 *string, err error)

func (*ApkParser) ParseXml

func (p *ApkParser) ParseXml(name string) error

type Application

type Application struct {
	Icon  androidbinary.String `xml:"http://schemas.android.com/apk/res/android icon,attr"`
	Label androidbinary.String `xml:"http://schemas.android.com/apk/res/android label,attr"`
	Name  androidbinary.String `xml:"http://schemas.android.com/apk/res/android name,attr"`
}

type AttrType

type AttrType uint8

type IconData

type IconData struct {
	Name      string
	Icon      *string
	IconBytes []byte
}

type Manifest

type Manifest struct {
	Package     androidbinary.String `xml:"package,attr"`
	VersionCode androidbinary.Int32  `xml:"http://schemas.android.com/apk/res/android versionCode,attr"`
	VersionName androidbinary.String `xml:"http://schemas.android.com/apk/res/android versionName,attr"`
	App         Application          `xml:"application"`
}

type ManifestEncoder

type ManifestEncoder interface {
	EncodeToken(t xml.Token) error
	Flush() error
}

Encoder for writing the XML data. For example Encoder from encoding/xml matches this interface.

type ResourceConfigOption

type ResourceConfigOption int

Resource config option to pick from options - when @drawable/icon is referenced, use /res/drawable-xhdpi/icon.png or use /res/drawable-mdpi/icon.png?

This is not fully implemented, so you can pick only first seen or last seen option.

const (
	ConfigFirst ResourceConfigOption = iota // Usually the smallest
	ConfigLast                              // Usually the biggest

	// Try to find the biggest png icon, otherwise same as ConfigLast.
	//
	// Deprecated: use GetIconPng
	ConfigPngIcon
)

type ResourceEntry

type ResourceEntry struct {
	ResourceType string
	Key          string
	Package      string
	// contains filtered or unexported fields
}

Describes one resource entry, for example @drawable/icon in the original XML, in one particular config option.

func (*ResourceEntry) GetValue

func (e *ResourceEntry) GetValue() *ResourceValue

Returns the resource value handle

func (*ResourceEntry) IsComplex

func (e *ResourceEntry) IsComplex() bool

Returns true if the resource entry is complex (for example arrays, string plural arrays...).

Complex ResourceEntries are not yet supported.

type ResourceTable

type ResourceTable struct {
	// contains filtered or unexported fields
}

Contains parsed resources.arsc file.

func ParseResourceTable

func ParseResourceTable(r io.Reader) (*ResourceTable, error)

Parses the resources.arsc file

func (*ResourceTable) GetIconPng

func (x *ResourceTable) GetIconPng(resId uint32) (*ResourceEntry, error)

Return the biggest last config ending with .png. Falls back to GetResourceEntry() if none found.

func (*ResourceTable) GetResourceEntry

func (x *ResourceTable) GetResourceEntry(resId uint32) (*ResourceEntry, error)

Returns the resource entry for resId and the first configuration option it finds.

func (*ResourceTable) GetResourceEntryEx

func (x *ResourceTable) GetResourceEntryEx(resId uint32, config ResourceConfigOption) (*ResourceEntry, error)

Returns the resource entry for resId and config configuration option.

func (*ResourceTable) GetResourceName

func (x *ResourceTable) GetResourceName(resId uint32) (string, error)

Converts the resource id to readable name including the package name like "@drawable:com.example.app.icon".

type ResourceValue

type ResourceValue struct {
	// contains filtered or unexported fields
}

Handle to the resource's actual value.

func (*ResourceValue) Data

func (v *ResourceValue) Data() (interface{}, error)

Returns the data converted to their native type (e.g. AttrTypeString to string).

Returns ErrUnknownResourceDataType if the type is not handled by this library

func (*ResourceValue) RawData

func (v *ResourceValue) RawData() uint32

Returns the raw data of the resource

func (*ResourceValue) String

func (v *ResourceValue) String() (res string, err error)

Returns the data converted to a readable string, to the format it was likely in the original AndroidManifest.xml.

Unknown data types are returned as the string from ErrUnknownResourceDataType.Error().

func (*ResourceValue) Type

func (v *ResourceValue) Type() AttrType

Returns the resource data type

type ZipReader

type ZipReader struct {
	File map[string]*ZipReaderFile

	// Files in the order they were found in the zip. May contain the same ZipReaderFile
	// multiple times in case of broken/crafted ZIPs
	FilesOrdered []*ZipReaderFile
	// contains filtered or unexported fields
}

This struct mimics of Reader from archive/zip. It's purpose is to handle even broken archives that Android can read, but archive/zip cannot.

func OpenZip

func OpenZip(path string) (zr *ZipReader, err error)

Attempts to open ZIP for reading.

func OpenZipReader

func OpenZipReader(zipReader io.ReadSeeker) (zr *ZipReader, err error)

Attempts to open ZIP for reading. Might Seek the reader to arbitrary positions.

func (*ZipReader) Close

func (zr *ZipReader) Close() error

Closes this ZIP archive and all it's ZipReaderFile entries.

type ZipReaderFile

type ZipReaderFile struct {
	Name  string
	IsDir bool
	// contains filtered or unexported fields
}

This struct mimics of File from archive/zip. The main difference is it can represent multiple actual entries in the ZIP file in case it has more than one with the same name.

func (*ZipReaderFile) Close

func (zr *ZipReaderFile) Close() error

Closes this reader and all opened files.

func (*ZipReaderFile) Next

func (zr *ZipReaderFile) Next() bool

Moves this reader to the next file represented under it's Name. Returns false if there are no more to read.

func (*ZipReaderFile) Open

func (zr *ZipReaderFile) Open() error

Opens the file(s) for reading. After calling open, you should iterate through all possible entries that go by that Filename with for f.Next() { f.Read()... }

func (*ZipReaderFile) Read

func (zr *ZipReaderFile) Read(p []byte) (int, error)

Reads data from current opened file. Returns io.EOF at the end of current file, but another file entry might exist. Use Next() to check for that.

func (*ZipReaderFile) ZipHeader

func (zr *ZipReaderFile) ZipHeader() *zip.FileHeader

Get the file header from ZIP (can return nil with broken archives)

Directories

Path Synopsis
This is a tool to extract AndroidManifest.xml from apks and verify their signatures.
This is a tool to extract AndroidManifest.xml from apks and verify their signatures.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL