-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🚀 new version! Export to JSON, dump additional metadata and refactor …
…code!
- Loading branch information
1 parent
b7dc729
commit ee81d5c
Showing
12 changed files
with
793 additions
and
486 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,82 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"encoding/json" | ||
"os" | ||
|
||
"github.com/shogo82148/androidbinary/apk" | ||
) | ||
|
||
// permissionsInfo(apk) - get the permission from apk | ||
func permissionsInfo(apk apk.Apk) { | ||
if len(apk.Manifest().UsesPermissions) == 0 { | ||
italic.Println("no permissions found") | ||
} else { | ||
for _, n := range apk.Manifest().UsesPermissions { | ||
permission, _ := n.Name.String() | ||
if permission != "" { | ||
fmt.Println(permission) | ||
} | ||
} | ||
} | ||
// AndroidApp represents information extracted from an APK file | ||
type AndroidApp struct { | ||
Name string `json:"name"` | ||
PackageName string `json:"package-name"` | ||
Version string `json:"version"` | ||
MainActivity string `json:"main-activity"` | ||
MinimumSDK int32 `json:"minimum-sdk"` | ||
TargetSDK int32 `json:"target-sdk"` | ||
Hashes Hashes `json:"hashes"` | ||
Permissions []string `json:"permissions"` | ||
Metadata []Metadata `json:"metadata"` | ||
Certificate CertificateInfo `json:"certificate"` | ||
PlayStore *PlayStoreInfo `json:"playstore,omitempty"` | ||
Koodous *KoodousInfo `json:"koodous,omitempty"` | ||
VirusTotal *VirusTotalInfo `json:"virustotal,omitempty"` | ||
} | ||
|
||
// metadataInfo(apk) - get the metadata from apk | ||
func metadataInfo(apk apk.Apk) { | ||
if len(apk.Manifest().App.MetaData) == 0 { | ||
italic.Println("no metadata found") | ||
} else { | ||
for _, n := range apk.Manifest().App.MetaData { | ||
metaname, _ := n.Name.String() | ||
metavalue, _ := n.Value.String() | ||
fmt.Printf("%s: ", metaname) | ||
if metavalue != "" { | ||
cyan.Printf("%s", metavalue) | ||
} | ||
fmt.Printf("\n") | ||
} | ||
} | ||
// Hashes represents hash values | ||
type Hashes struct { | ||
Md5 string `json:"md5"` | ||
Sha1 string `json:"sha1"` | ||
Sha256 string `json:"sha256"` | ||
} | ||
|
||
// getGeneralInfo(apk) - get general info from apk | ||
func generalInfo(apk apk.Apk) { | ||
|
||
yellow.Printf("\nApp name:\t") | ||
name, err := apk.Label(nil) | ||
if err == nil { | ||
cyan.Printf("%s\n", name) | ||
} else { | ||
italic.Printf("app name not found\n") | ||
} | ||
|
||
yellow.Println("\n* General Info") | ||
|
||
fmt.Printf("PackageName:\t") | ||
printer(apk.PackageName()) | ||
|
||
fmt.Printf("App version:\t") | ||
version, err := apk.Manifest().VersionName.String() | ||
if err != nil { | ||
version = "" | ||
} | ||
printer(version) | ||
// Metadata represents metadata | ||
type Metadata struct { | ||
Name string `json:"name"` | ||
Value string `json:"value,omitempty"` | ||
} | ||
|
||
fmt.Printf("Main activity:\t") | ||
mainactivity, err := apk.MainActivity() | ||
// ExportJSON exports AndroidApp struct to a JSON file | ||
func (app *AndroidApp) ExportJSON(jsonpath string) error { | ||
jsonfile, err := json.MarshalIndent(app, "", "\t") | ||
if err != nil { | ||
mainactivity = "" | ||
return err | ||
} | ||
printer(mainactivity) | ||
err = os.WriteFile(jsonpath, jsonfile, 0644) | ||
return err | ||
} | ||
|
||
fmt.Printf("Minimum SDK:\t") | ||
sdkmin, err := apk.Manifest().SDK.Min.Int32() | ||
if err != nil { | ||
italic.Println("not found") | ||
} else { | ||
cyan.Printf("%d (%s)\n", sdkmin, androidname[int(sdkmin)]) | ||
// setGeneralInfo sets general information about the APK | ||
func (app *AndroidApp) setGeneralInfo(apk *apk.Apk) { | ||
name, _ := apk.Label(nil) | ||
app.Name = name | ||
app.PackageName = apk.PackageName() | ||
version, _ := apk.Manifest().VersionName.String() | ||
app.Version = version | ||
main, _ := apk.MainActivity() | ||
app.MainActivity = main | ||
sdkMin, _ := apk.Manifest().SDK.Min.Int32() | ||
app.MinimumSDK = sdkMin | ||
sdkTarget, _ := apk.Manifest().SDK.Target.Int32() | ||
app.TargetSDK = sdkTarget | ||
for _, n := range apk.Manifest().UsesPermissions { | ||
permission, _ := n.Name.String() | ||
if permission != "" { | ||
app.Permissions = append(app.Permissions, permission) | ||
} | ||
} | ||
|
||
fmt.Printf("Target SDK:\t") | ||
sdktarget, err := apk.Manifest().SDK.Target.Int32() | ||
if err != nil { | ||
italic.Println("not found") | ||
} else { | ||
cyan.Printf("%d (%s)\n", sdktarget, androidname[int(sdktarget)]) | ||
var m Metadata | ||
for _, n := range apk.Manifest().App.MetaData { | ||
metadataName, _ := n.Name.String() | ||
metadataValue, _ := n.Value.String() | ||
if metadataName != "" { | ||
m.Name = metadataName | ||
m.Value = "" | ||
if metadataValue != "" { | ||
m.Value = metadataValue | ||
} | ||
app.Metadata = append(app.Metadata, m) | ||
} | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,76 @@ | ||
package main | ||
|
||
import ( | ||
"crypto/x509/pkix" | ||
"encoding/hex" | ||
"errors" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/avast/apkverifier" | ||
) | ||
|
||
// certInfo(path) - retrieve certificate information from apk | ||
func certInfo(filepath string) error { | ||
// CertificateInfo represents certificate information | ||
type CertificateInfo struct { | ||
Serial string `json:"serial"` | ||
Thumbprint string `json:"thumbprint"` | ||
ValidFrom string `json:"valid-from"` | ||
ValidTo string `json:"valid-to"` | ||
Subject CertName `json:"subject"` | ||
Issuer CertName `json:"issuer"` | ||
} | ||
|
||
// CertName represents issuer and subject details | ||
type CertName struct { | ||
Country string `json:"country"` | ||
Organization string `json:"organization"` | ||
OrgUnit string `json:"organizational-unit"` | ||
Locality string `json:"locality"` | ||
Province string `json:"province"` | ||
CommonName string `json:"common-name"` | ||
Raw string `json:"raw"` | ||
} | ||
|
||
// setCertName sets certificate name details | ||
func (cn *CertName) setCertName(name pkix.Name) { | ||
cn.Country = firstElement(name.Country) | ||
cn.Organization = firstElement(name.Organization) | ||
cn.OrgUnit = firstElement(name.OrganizationalUnit) | ||
cn.Locality = firstElement(name.Locality) | ||
cn.Province = firstElement(name.Province) | ||
cn.CommonName = name.CommonName | ||
} | ||
|
||
// firstElement returns the first element of a string slice, or an empty string if the slice is empty | ||
func firstElement(slice []string) string { | ||
if len(slice) > 0 { | ||
return slice[0] | ||
} | ||
return "" | ||
} | ||
|
||
// setCertInfo retrieves and sets certificate information | ||
func (androidapp *AndroidApp) setCertInfo(filepath string) error { | ||
res, err := apkverifier.ExtractCerts(filepath, nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// this may print an error, but certificate info are still retrieved | ||
cert, _ := apkverifier.PickBestApkCert(res) | ||
cert, certx := apkverifier.PickBestApkCert(res) | ||
if cert == nil { | ||
return errors.New("no certificate found") | ||
} | ||
|
||
fmt.Printf("Serial:\t\t") | ||
printer(cert.SerialNumber.String()) | ||
fmt.Printf("sha1:\t\t") | ||
printer(cert.Sha1) | ||
fmt.Printf("Issuer:\t\t") | ||
printer(cert.Issuer) | ||
fmt.Printf("Subject:\t") | ||
printer(cert.Subject) | ||
fmt.Printf("Valid from:\t") | ||
printer(cert.ValidFrom.Format(time.RFC822)) | ||
fmt.Printf("Valid to:\t") | ||
printer(cert.ValidTo.Format(time.RFC822)) | ||
androidapp.Certificate.Serial = hex.EncodeToString(cert.SerialNumber.Bytes()) | ||
androidapp.Certificate.Thumbprint = cert.Sha1 | ||
androidapp.Certificate.ValidFrom = cert.ValidFrom.Format(time.DateTime) | ||
androidapp.Certificate.ValidTo = cert.ValidTo.Format(time.DateTime) | ||
|
||
if certx != nil { | ||
androidapp.Certificate.Subject.setCertName(certx.Subject) | ||
androidapp.Certificate.Issuer.setCertName(certx.Issuer) | ||
} | ||
androidapp.Certificate.Subject.Raw = cert.Subject | ||
androidapp.Certificate.Issuer.Raw = cert.Issuer | ||
|
||
return nil | ||
} |
This file contains 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
Oops, something went wrong.