apkparser

package module
v0.0.0-...-8725823 Latest Latest
Warning

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

Go to latest
Published: Feb 13, 2025 License: LGPL-3.0 Imports: 24 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/avast/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/avast/apkparser
go install github.com/avast/apkparser/axml2xml
./axml2xml -v application.apk

Example

package main

import (
	"encoding/xml"
	"fmt"
	"github.com/avast/apkparser"
	"os"
)

func main() {
	enc := xml.NewEncoder(os.Stdout)
	enc.Indent("", "\t")
	zipErr, resErr, manErr := apkparser.ParseApk(os.Args[1], enc)
	if zipErr != nil {
		fmt.Fprintf(os.Stderr, "Failed to open the APK: %s", zipErr.Error())
		os.Exit(1)
		return
	}

	if resErr != nil {
		fmt.Fprintf(os.Stderr, "Failed to parse resources: %s", resErr.Error())
	}
	if manErr != nil {
		fmt.Fprintf(os.Stderr, "Failed to parse AndroidManifest.xml: %s", manErr.Error())
		os.Exit(1)
		return
	}
	fmt.Println()
}

Documentation

Overview

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

Example
package main

import (
	"fmt"
	"github.com/csturiale/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 ParseResID

func ParseResID(s string) (uint32, error)

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 ActivityAction

type ActivityAction struct {
	Name string `xml:"http://schemas.android.com/apk/res/android name,attr"`
}

ActivityAction is an action of an activity.

type ActivityCategory

type ActivityCategory struct {
	Name string `xml:"http://schemas.android.com/apk/res/android name,attr"`
}

ActivityCategory is a category of an activity.

type ActivityIntentFilter

type ActivityIntentFilter struct {
	Actions    []ActivityAction   `xml:"action"`
	Categories []ActivityCategory `xml:"category"`
}

ActivityIntentFilter is an int32ent filter of an activity.

type AdaptiveIcon

type AdaptiveIcon struct {
	Background struct {
		Drawable string `xml:"http://schemas.android.com/apk/res/android drawable,attr"`
	} `xml:"background"`
	Foreground struct {
		Drawable string `xml:"http://schemas.android.com/apk/res/android drawable,attr"`
	} `xml:"foreground"`
}

type ApkInfo

type ApkInfo struct {
	Manifest Manifest
	Icon     image.Image
}

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) (image.Image, error)

func (*ApkParser) ParseXml

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

type AppActivity

type AppActivity struct {
	Theme             string                 `xml:"http://schemas.android.com/apk/res/android theme,attr"`
	Name              string                 `xml:"http://schemas.android.com/apk/res/android name,attr"`
	Label             string                 `xml:"http://schemas.android.com/apk/res/android label,attr"`
	ScreenOrientation string                 `xml:"http://schemas.android.com/apk/res/android screenOrientation,attr"`
	IntentFilters     []ActivityIntentFilter `xml:"intent-filter"`
}

AppActivity is an activity in an application.

type AppActivityAlias

type AppActivityAlias struct {
	Name           string                 `xml:"http://schemas.android.com/apk/res/android name,attr"`
	Label          string                 `xml:"http://schemas.android.com/apk/res/android label,attr"`
	TargetActivity string                 `xml:"http://schemas.android.com/apk/res/android targetActivity,attr"`
	IntentFilters  []ActivityIntentFilter `xml:"intent-filter"`
}

AppActivityAlias https://developer.android.com/guide/topics/manifest/activity-alias-element

type Application

type Application struct {
	AllowTaskReparenting  bool               `xml:"http://schemas.android.com/apk/res/android allowTaskReparenting,attr"`
	AllowBackup           bool               `xml:"http://schemas.android.com/apk/res/android allowBackup,attr"`
	BackupAgent           string             `xml:"http://schemas.android.com/apk/res/android backupAgent,attr"`
	Debuggable            bool               `xml:"http://schemas.android.com/apk/res/android debuggable,attr"`
	Description           string             `xml:"http://schemas.android.com/apk/res/android description,attr"`
	Enabled               bool               `xml:"http://schemas.android.com/apk/res/android enabled,attr"`
	HasCode               bool               `xml:"http://schemas.android.com/apk/res/android hasCode,attr"`
	HardwareAccelerated   bool               `xml:"http://schemas.android.com/apk/res/android hardwareAccelerated,attr"`
	Icon                  string             `xml:"http://schemas.android.com/apk/res/android icon,attr"`
	KillAfterRestore      bool               `xml:"http://schemas.android.com/apk/res/android killAfterRestore,attr"`
	LargeHeap             bool               `xml:"http://schemas.android.com/apk/res/android largeHeap,attr"`
	Label                 string             `xml:"http://schemas.android.com/apk/res/android label,attr"`
	ManageSpaceActivity   string             `xml:"http://schemas.android.com/apk/res/android manageSpaceActivity,attr"`
	Name                  string             `xml:"http://schemas.android.com/apk/res/android name,attr"`
	Permission            string             `xml:"http://schemas.android.com/apk/res/android permission,attr"`
	Persistent            bool               `xml:"http://schemas.android.com/apk/res/android persistent,attr"`
	Process               string             `xml:"http://schemas.android.com/apk/res/android process,attr"`
	RestoreAnyVersion     bool               `xml:"http://schemas.android.com/apk/res/android restoreAnyVersion,attr"`
	RequiredAccountType   string             `xml:"http://schemas.android.com/apk/res/android requiredAccountType,attr"`
	RestrictedAccountType string             `xml:"http://schemas.android.com/apk/res/android restrictedAccountType,attr"`
	SupportsRtl           bool               `xml:"http://schemas.android.com/apk/res/android supportsRtl,attr"`
	TaskAffinity          string             `xml:"http://schemas.android.com/apk/res/android taskAffinity,attr"`
	TestOnly              bool               `xml:"http://schemas.android.com/apk/res/android testOnly,attr"`
	Theme                 string             `xml:"http://schemas.android.com/apk/res/android theme,attr"`
	UIOptions             string             `xml:"http://schemas.android.com/apk/res/android uiOptions,attr"`
	VMSafeMode            bool               `xml:"http://schemas.android.com/apk/res/android vmSafeMode,attr"`
	Activities            []AppActivity      `xml:"activity"`
	ActivityAliases       []AppActivityAlias `xml:"activity-alias"`
	MetaData              []MetaData         `xml:"meta-data"`
}

Application is an application in an APK.

type AttrType

type AttrType uint8

type Instrumentation

type Instrumentation struct {
	Name            string `xml:"http://schemas.android.com/apk/res/android name,attr"`
	Target          string `xml:"http://schemas.android.com/apk/res/android targetPackage,attr"`
	HandleProfiling bool   `xml:"http://schemas.android.com/apk/res/android handleProfiling,attr"`
	FunctionalTest  bool   `xml:"http://schemas.android.com/apk/res/android functionalTest,attr"`
}

type Manifest

type Manifest struct {
	Package                   string           `xml:"package,attr"`
	CompileSDKVersion         int32            `xml:"http://schemas.android.com/apk/res/android compileSdkVersion,attr"`
	CompileSDKVersionCodename string           `xml:"http://schemas.android.com/apk/res/android compileSdkVersionCodename,attr"`
	VersionCode               int32            `xml:"http://schemas.android.com/apk/res/android versionCode,attr"`
	VersionName               string           `xml:"http://schemas.android.com/apk/res/android versionName,attr"`
	App                       Application      `xml:"application"`
	Instrument                Instrumentation  `xml:"instrumentation"`
	SDK                       UsesSDK          `xml:"uses-sdk"`
	UsesPermissions           []UsesPermission `xml:"uses-permission"`
}

Manifest is a manifest of an APK.

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 MetaData

type MetaData struct {
	Name  string `xml:"http://schemas.android.com/apk/res/android name,attr"`
	Value string `xml:"http://schemas.android.com/apk/res/android value,attr"`
}

MetaData is a metadata in an application.

type ResAttr

type ResAttr struct {
	NamespaceId uint32
	NameIdx     uint32
	RawValueIdx uint32
	Res         ResValue
}

type ResValue

type ResValue struct {
	Size uint16
	Res0 uint8 // padding
	Type AttrType
	Data uint32
}

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 UsesPermission

type UsesPermission struct {
	Name string `xml:"http://schemas.android.com/apk/res/android name,attr"`
	Max  int32  `xml:"http://schemas.android.com/apk/res/android maxSdkVersion,attr"`
}

UsesPermission is user grant the system permission.

type UsesSDK

type UsesSDK struct {
	Min    int32 `xml:"http://schemas.android.com/apk/res/android minSdkVersion,attr"`
	Target int32 `xml:"http://schemas.android.com/apk/res/android targetSdkVersion,attr"`
	Max    int32 `xml:"http://schemas.android.com/apk/res/android maxSdkVersion,attr"`
}

UsesSDK is target SDK version.

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) ReadAll

func (zr *ZipReaderFile) ReadAll(limit int64) ([]byte, error)

Open, Read all bytes until limit and close the file

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