Lompat ke konten
dokumentasi.id
Commit dd5271a
v1
Star6,4 rb

Kamu membaca versi lama. Halaman ini hanya bisa dibaca.

5

Mesin Pemindaian Pola

APKLeaks.scanning() adalah tahap ketiga dalam satu kali eksekusi: cli.main memanggil integrity(), decompile(), lalu scanning(), dan cleanup() selalu dijalankan lewat blok finally (apkleaks/cli.py:36-41). Metode ini memuat berkas pola, menjalankannya pada direktori hasil dekompilasi, dan menyerahkan tiap kelompok match ke satu thread. Isi lengkapnya ada di apkleaks/apkleaks.py:117-138.

Bila self.apk masih None, scanning() langsung berhenti dengan pesan ** Undefined package. Exit! (apkleaks/apkleaks.py:118-119). Bila tidak, ia mencetak ** Scanning against '<package>' lalu menyiapkan self.out_json["package"] dan self.out_json["results"] = [] sebelum pola pertama dibaca (apkleaks/apkleaks.py:120-122).

Urutan pemanggilan scanning()

Diagram berikut menunjukkan interaksi nyata di dalam scanning(), termasuk fakta bahwa util.finder dipanggil lebih dulu sebagai argumen, baru setelah itu threading.Thread dibuat.

sequenceDiagram
    participant CLI as cli.main
    participant L as APKLeaks
    participant FS as config/regexes.json
    participant U as util.finder
    participant T as threading.Thread
    participant E as APKLeaks.extract
    CLI->>L: scanning()
    L->>L: cek self.apk is None
    L->>FS: open(self.pattern)
    FS-->>L: json.load(regexes)
    loop setiap name, pattern di regex.items()
        alt isinstance pattern, list
            L->>U: finder p untuk satu elemen
        else
            L->>U: finder pattern tunggal
        end
        U-->>L: matches terurut dan unik
        L->>T: Thread target self.extract
        L->>T: thread.start()
        T->>E: extract(name, matches)
        E->>E: self.out_json results append
        E->>E: self.scanned = True
    end
    Note over CLI,L: cleanup() dijalankan di blok finally
%% fig: Alur scanning sampai extract per pola
%% desc: scanning membaca regexes.json, menjalankan util.finder di thread utama, lalu memulai satu thread yang memanggil extract untuk setiap pola.
Fig. 1: Alur scanning sampai extract per polascanning membaca regexes.json, menjalankan util.finder di thread utama, lalu memulai satu thread yang memanggil extract untuk setiap pola.

Berkas pola dibuka dengan open(self.pattern) lalu diurai dengan json.load, sehingga urutan iterasi mengikuti urutan key di dalam JSON (apkleaks/apkleaks.py:123-124). Setiap key menjadi name dan setiap nilai menjadi pattern; cabang isinstance(pattern, list) memisahkan pola tunggal dari pola berbentuk daftar (apkleaks/apkleaks.py:125-127).

Atribut yang menentukan pemindaian

scanning() tidak menerima parameter; seluruh masukannya berasal dari atribut yang disiapkan di __init__ (apkleaks/apkleaks.py:31-37).

AtributDiisi diPeran di scanning()
self.apkintegrity()sumber self.apk.package untuk pesan dan out_json["package"]; bila None, proses berhenti
self.pattern__init__path config/regexes.json atau nilai args.pattern
self.tempdir__init__akar direktori hasil decompile() yang diserahkan ke util.finder
self.fileout__init__handle berkas tujuan tulisan extract
self.out_json__init__akumulasi {"package": ..., "results": [...]}
self.scannedextract()penanda apakah ada hasil; dibaca cleanup()

Baris self.pattern menetapkan nilai default config/regexes.json hanya ketika args.pattern tidak diberikan, sehingga halaman Pola Kustom berlaku saat pengguna mengganti path tersebut (apkleaks/apkleaks.py:35).

Bentuk nilai di regexes.json

Jumlah thread yang dibuat sama dengan jumlah pola yang dieksekusi, bukan jumlah key. Satu key boleh berupa daftar, dan setiap elemennya mendapat thread sendiri dengan name yang sama.

Bentuk nilaiContoh keyBarisPenanganan
string tunggalAmazon_AWS_Access_Key_IDconfig/regexes.json:2satu panggilan util.finder, satu thread
list stringAmazon_AWS_S3_Bucket berisi 6 regexconfig/regexes.json:3-10satu panggilan util.finder dan satu thread per elemen, name tetap

Untuk cabang string tunggal, pembuatan thread berada di dalam blok try yang hanya menangkap KeyboardInterrupt (apkleaks/apkleaks.py:134-136). Cabang list memperlakukan hal yang sama di dalam loop for p in pattern (apkleaks/apkleaks.py:129-130). Daftar nama pola bawaan diuraikan di halaman Katalog Pola Bawaan.

util.finder: satu pola, satu lintasan penuh

util.finder adalah staticmethod yang menerima pattern dan path, lalu mengembalikan daftar match (apkleaks/utils.py:16-31). Gambar berikut menunjukkan perpindahan data di dalamnya.

graph LR
  A["self.tempdir<br/>hasil decompile jadx"] --> B["util.finder(pattern, path)"]
  B --> C["re.compile(pattern)"]
  B --> D["os.walk(path)"]
  D --> E["open(filepath)"]
  E --> F["matcher.search(line)"]
  F --> G["found.append(mo.group())"]
  F --> X["continue ke line berikutnya"]
  G --> H["sorted(list(set(found)))"]
  E --> Z["except Exception: pass"]
  H --> I["APKLeaks.extract"]
  style A fill:#336791,color:#fff
  style B fill:#f59e0b,color:#000
  style C fill:#f59e0b,color:#000
  style G fill:#8b5cf6,color:#fff
  style H fill:#8b5cf6,color:#fff
  style I fill:#2d7d46,color:#fff
  style Z fill:#dc2626,color:#fff
  style X fill:#2d7d46,color:#fff
%% fig: Perjalanan data di util.finder
%% desc: Setiap pola dikompilasi sekali, seluruh berkas di tempdir dibaca baris per baris, lalu match dideduplikasi dan diurutkan sebelum diserahkan ke extract.
Fig. 2: Perjalanan data di util.finderSetiap pola dikompilasi sekali, seluruh berkas di tempdir dibaca baris per baris, lalu match dideduplikasi dan diurutkan sebelum diserahkan ke extract.

Tiga sifat fungsi ini menentukan biaya pemindaian:

  • re.compile(pattern) dijalankan sekali per pola, lalu satu for loop os.walk(path) menelusuri seluruh direktori hasil dekompilasi (apkleaks/utils.py:18, apkleaks/utils.py:20-22). Karena finder dipanggil sekali per pola, berkas yang sama dibaca ulang sebanyak jumlah pola.
  • Setiap berkas dibuka dengan open(filepath) lalu dibaca dengan handle.readlines(); nilai yang cocok diambil lewat matcher.search(line) dan disimpan sebagai mo.group(), bukan sebagai satu baris penuh (apkleaks/utils.py:23-30).
  • Galat saat membaca baris ditelan except Exception: pass, sehingga berkas yang gagal didekode dilewati tanpa menghentikan pemindaian (apkleaks/utils.py:29-30). Namun open(filepath) sendiri berada di luar blok try, sehingga kegagalan membuka berkas naik ke pemanggil.
  • Hasil dikembalikan sebagai sorted(list(set(found))), jadi duplikat dihapus dan urutan match stabil (apkleaks/utils.py:31).

⚠️ re.compile berjalan di thread utama karena util.finder(...) dievaluasi sebagai argumen args=(name, ...) sebelum thread.start(). Pola yang tidak valid karenanya melempar re.error di jalur utama, dan blok try di scanning() hanya menangkap KeyboardInterrupt (apkleaks/apkleaks.py:129-130, apkleaks/apkleaks.py:134-136).

extract: menyaring dan menyimpan hasil

extract(name, matches) hanya bekerja bila len(matches) tidak nol (apkleaks/apkleaks.py:100-115). Ia mencetak judul [<name>] dengan warna col.OKGREEN, menulis setiap match sebagai - <secret> ke self.fileout, lalu menambahkan {"name": name, "matches": matches} ke self.out_json["results"] dan menyalakan self.scanned = True (apkleaks/apkleaks.py:114-115). Rincian bentuk keluaran ada di halaman Format Keluaran.

Satu pengecualian khusus berlaku untuk pola bernama LinkFinder: match yang diawali tipe resource Android dibuang lewat re.match(r"^.(L[a-z]|application|audio|fonts|image|kotlin|layout|multipart|plain|text|video).*\/.+", secret), dan tanda kutip pembuka serta penutup dipangkas dengan secret[len("'"):-len("'")] (apkleaks/apkleaks.py:106-109).

⚠️ Thread tidak pernah di-join dan tidak ada pembatasan jumlah thread: scanning() memanggil thread.start() untuk setiap pola lalu langsung lanjut ke pola berikutnya (apkleaks/apkleaks.py:129-130). extract juga menulis self.fileout dan self.out_json["results"] dari banyak thread tanpa lock, sehingga urutan baris dan urutan entri results mengikuti penjadwalan thread, bukan urutan key di regexes.json (apkleaks/apkleaks.py:114-115).

Karena cleanup() berjalan di blok finally tanpa menunggu thread, hasil yang masih ditulis saat proses selesai dapat hilang; cleanup() hanya menyimpan JSON bila self.scanned bernilai benar (apkleaks/apkleaks.py:140-148). Tahap sebelumnya yang menghasilkan self.tempdir dibahas di halaman Dekomplikasi dan jadx, sedangkan posisi scanning() dalam keseluruhan alur ada di halaman Alur Pemindaian.