Skip to content

Commit ad2d1fc

Browse files
committed
Improve output formatting and organization
1 parent 86accc5 commit ad2d1fc

File tree

2 files changed

+54
-39
lines changed

2 files changed

+54
-39
lines changed

analyzer/aapt2_extractor.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ func (a *AAPT2Extractor) IsAvailable() bool {
3333
if a.cfg.Verbose {
3434
log.Printf("[AAPT2] Found aapt2 at: %s", path)
3535
} else {
36-
log.Printf("✓ aapt2 tool found")
3736
}
3837
return true
3938
}

cmd/output.go

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -230,19 +230,30 @@ func displayOutputSummary(results *models.Results, outDir string, allURLs []stri
230230
targetSDK = results.AppInfo.TargetSDK
231231
}
232232

233-
fmt.Fprintf(os.Stderr, "\n📊 Analysis Results\n")
234-
fmt.Fprintf(os.Stderr, " Saved to: %s\n", outDir)
233+
fmt.Fprintf(os.Stderr, "\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
234+
fmt.Fprintf(os.Stderr, "📊 ANALYSIS RESULTS\n")
235+
fmt.Fprintf(os.Stderr, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n")
236+
237+
// App Info Section
235238
if pkg != "" {
236-
if verName != "" || verCode != "" {
237-
fmt.Fprintf(os.Stderr, " App: %s (v%s, code %s)\n", pkg, safeStr(verName), safeStr(verCode))
238-
} else {
239-
fmt.Fprintf(os.Stderr, " App: %s\n", pkg)
239+
fmt.Fprintf(os.Stderr, "📦 APP INFORMATION\n")
240+
fmt.Fprintf(os.Stderr, " Package: %s\n", pkg)
241+
if verName != "" {
242+
fmt.Fprintf(os.Stderr, " Version: %s", verName)
243+
if verCode != "" {
244+
fmt.Fprintf(os.Stderr, " (build %s)\n", verCode)
245+
} else {
246+
fmt.Fprintf(os.Stderr, "\n")
247+
}
240248
}
249+
if minSDK != "" || targetSDK != "" {
250+
fmt.Fprintf(os.Stderr, " SDK: min %s → target %s\n", safeStr(minSDK), safeStr(targetSDK))
251+
}
252+
if hasDecompiled {
253+
fmt.Fprintf(os.Stderr, " Source: Full APK decompiled\n")
254+
}
255+
fmt.Fprintln(os.Stderr)
241256
}
242-
if minSDK != "" || targetSDK != "" {
243-
fmt.Fprintf(os.Stderr, " SDK: min %s, target %s\n", safeStr(minSDK), safeStr(targetSDK))
244-
}
245-
fmt.Fprintln(os.Stderr)
246257

247258
// High-level stats
248259
type kv struct {
@@ -260,10 +271,9 @@ func displayOutputSummary(results *models.Results, outDir string, allURLs []stri
260271
{"🔗 Services", len(results.Services)},
261272
{"🎨 Assets", assetCount},
262273
}
263-
if hasDecompiled {
264-
fmt.Fprintf(os.Stderr, " 📁 Decompiled: Full APK source\n")
265-
}
274+
266275
// Print stats in two columns
276+
fmt.Fprintf(os.Stderr, "📊 FINDINGS SUMMARY\n")
267277
printed := 0
268278
for _, s := range stats {
269279
if s.v > 0 {
@@ -279,6 +289,7 @@ func displayOutputSummary(results *models.Results, outDir string, allURLs []stri
279289
if printed%2 != 0 {
280290
fmt.Fprintln(os.Stderr)
281291
}
292+
fmt.Fprintln(os.Stderr)
282293

283294
// Highlights (top items)
284295
showTop := func(title string, items []string, limit int) {
@@ -289,17 +300,18 @@ func displayOutputSummary(results *models.Results, outDir string, allURLs []stri
289300
if len(items) < n {
290301
n = len(items)
291302
}
292-
fmt.Fprintf(os.Stderr, "\n%s:\n", title)
303+
fmt.Fprintf(os.Stderr, "🔝 %s (%d)\n", title, len(items))
293304
for i := 0; i < n; i++ {
294-
fmt.Fprintf(os.Stderr, " %s\n", items[i])
305+
fmt.Fprintf(os.Stderr, " %s\n", items[i])
295306
}
296307
if len(items) > n {
297-
fmt.Fprintf(os.Stderr, " …and %d more\n", len(items)-n)
308+
fmt.Fprintf(os.Stderr, " … and %d more\n", len(items)-n)
298309
}
310+
fmt.Fprintln(os.Stderr)
299311
}
300312

301313
if len(results.Domains) > 0 {
302-
showTop("Top domains", results.Domains, 5)
314+
showTop("Top Domains", results.Domains, 5)
303315
}
304316
if len(results.APIEndpoints) > 0 {
305317
eps := make([]string, 0, len(results.APIEndpoints))
@@ -310,10 +322,10 @@ func displayOutputSummary(results *models.Results, outDir string, allURLs []stri
310322
}
311323
eps = append(eps, fmt.Sprintf("%s %s", m, ep.URL))
312324
}
313-
showTop("API endpoints", eps, 5)
325+
showTop("API Endpoints", eps, 5)
314326
}
315327
if len(results.HardcodedKeys) > 0 {
316-
showTop("Potential secrets", results.HardcodedKeys, 5)
328+
showTop("Potential Secrets", results.HardcodedKeys, 5)
317329
}
318330

319331
// Security quick glance
@@ -336,61 +348,65 @@ func displayOutputSummary(results *models.Results, outDir string, allURLs []stri
336348
}
337349
if results.NetworkSecurity != nil {
338350
if results.NetworkSecurity.CleartextAllowed {
339-
securityLines = append(securityLines, "Cleartext traffic: allowed")
351+
securityLines = append(securityLines, "⚠️ Cleartext traffic: ALLOWED")
340352
} else {
341-
securityLines = append(securityLines, "Cleartext traffic: disallowed")
353+
securityLines = append(securityLines, "Cleartext traffic: disabled")
342354
}
343355
if results.NetworkSecurity.CertificatePinning {
344-
securityLines = append(securityLines, "Certificate pinning: enabled")
356+
securityLines = append(securityLines, "Certificate pinning: enabled")
345357
}
346358
}
347359
if results.Obfuscation != nil && results.Obfuscation.LikelyObfuscated {
348-
securityLines = append(securityLines, "Code obfuscation detected")
360+
securityLines = append(securityLines, "Code obfuscation: detected")
349361
}
350362
if len(securityLines) > 0 {
351-
fmt.Fprintf(os.Stderr, "\nSecurity:\n")
363+
fmt.Fprintf(os.Stderr, "🔒 SECURITY STATUS\n")
352364
for _, l := range securityLines {
353-
fmt.Fprintf(os.Stderr, " %s\n", l)
365+
fmt.Fprintf(os.Stderr, " %s\n", l)
354366
}
367+
fmt.Fprintln(os.Stderr)
355368
}
356369

357370
if verbose {
358-
fmt.Fprintf(os.Stderr, "\n📝 Files created:\n")
359-
fmt.Fprintf(os.Stderr, " ✓ summary.md (start here!)\n")
360-
fmt.Fprintf(os.Stderr, " ✓ analysis.json (full data)\n")
371+
fmt.Fprintf(os.Stderr, "📁 FILES GENERATED IN: %s\n", outDir)
372+
fmt.Fprintf(os.Stderr, " ✓ summary.md ← START HERE!\n")
373+
fmt.Fprintf(os.Stderr, " ✓ analysis.json (full report)\n")
361374
if len(results.Emails) > 0 {
362-
fmt.Fprintf(os.Stderr, " ✓ emails.txt\n")
375+
fmt.Fprintf(os.Stderr, " ✓ emails.txt (%d found)\n", len(results.Emails))
363376
}
364377
if len(results.Domains) > 0 {
365-
fmt.Fprintf(os.Stderr, " ✓ domains.txt\n")
378+
fmt.Fprintf(os.Stderr, " ✓ domains.txt (%d found)\n", len(results.Domains))
366379
}
367380
if len(allURLs) > 0 {
368-
fmt.Fprintf(os.Stderr, " ✓ urls.txt\n")
381+
fmt.Fprintf(os.Stderr, " ✓ urls.txt (%d found)\n", len(allURLs))
369382
}
370383
if len(results.APIEndpoints) > 0 {
371-
fmt.Fprintf(os.Stderr, " ✓ api_endpoints.txt\n")
384+
fmt.Fprintf(os.Stderr, " ✓ api_endpoints.txt (%d found)\n", len(results.APIEndpoints))
372385
}
373386
if len(results.Packages) > 0 {
374-
fmt.Fprintf(os.Stderr, " ✓ packages.txt\n")
387+
fmt.Fprintf(os.Stderr, " ✓ packages.txt (%d found)\n", len(results.Packages))
375388
}
376389
if len(results.Permissions) > 0 {
377-
fmt.Fprintf(os.Stderr, " ✓ permissions.txt\n")
390+
fmt.Fprintf(os.Stderr, " ✓ permissions.txt (%d found)\n", len(results.Permissions))
378391
}
379392
if len(results.HardcodedKeys) > 0 {
380-
fmt.Fprintf(os.Stderr, " ✓ hardcoded_keys.txt\n")
393+
fmt.Fprintf(os.Stderr, " ✓ hardcoded_keys.txt (%d found)\n", len(results.HardcodedKeys))
381394
}
382395
if len(results.Services) > 0 {
383-
fmt.Fprintf(os.Stderr, " ✓ services.txt\n")
396+
fmt.Fprintf(os.Stderr, " ✓ services.txt (%d found)\n", len(results.Services))
384397
}
385398
if assetCount > 0 {
386-
fmt.Fprintf(os.Stderr, " ✓ assets/ (organized by file type)\n")
399+
fmt.Fprintf(os.Stderr, " ✓ assets/ (%d files)\n", assetCount)
387400
}
388401
if hasDecompiled {
389402
fmt.Fprintf(os.Stderr, " ✓ decompiled/ (full APK source)\n")
390403
}
404+
fmt.Fprintln(os.Stderr)
391405
}
392406

393-
fmt.Fprintf(os.Stderr, "\n💡 Tip: Open summary.md in your editor or GitHub to see everything organized!\n\n")
407+
fmt.Fprintf(os.Stderr, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n")
408+
fmt.Fprintf(os.Stderr, "💡 Next: Open summary.md to review findings\n")
409+
fmt.Fprintf(os.Stderr, "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n")
394410
}
395411

396412
func sanitizeFileName(name string) string {

0 commit comments

Comments
 (0)