iOS Frida Configuration

Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι υποστήριξης του HackTricks:

WhiteIntel είναι μια μηχανή αναζήτησης που τροφοδοτείται από το dark web και προσφέρει δωρεάν λειτουργίες για να ελέγξετε αν μια εταιρεία ή οι πελάτες της έχουν διαρρεύσει από κλέφτες κακόβουλου λογισμικού.

Ο κύριος στόχος του WhiteIntel είναι η καταπολέμηση των αποκλεισμών λογαριασμών και των επιθέσεων ransomware που προκύπτουν από κακόβουλο λογισμικό που κλέβει πληροφορίες.

Μπορείτε να ελέγξετε την ιστοσελίδα τους και να δοκιμάσετε τη μηχανή τους δωρεάν στο:


Εγκατάσταση του Frida

Βήματα για να εγκαταστήσετε το Frida σε μια συσκευή με Jailbreak:

  1. Ανοίξτε την εφαρμογή Cydia/Sileo.

  2. Πλοηγηθείτε σε Διαχείριση -> Πηγές -> Επεξεργασία -> Προσθήκη.

  3. Εισαγάγετε "https://build.frida.re" ως URL.

  4. Μεταβείτε στη νεοπροσταθείσα πηγή του Frida.

  5. Εγκαταστήστε το πακέτο του Frida.

Αν χρησιμοποιείτε το Corellium θα πρέπει να κατεβάσετε την έκδοση του Frida από https://github.com/frida/frida/releases (frida-gadget-[yourversion]-ios-universal.dylib.gz) και να αποσυμπιέσετε και να αντιγράψετε στη θέση dylib που ζητάει το Frida, π.χ.: /Users/[youruser]/.cache/frida/gadget-ios.dylib

Μετά την εγκατάσταση, μπορείτε να χρησιμοποιήσετε στον υπολογιστή σας την εντολή frida-ls-devices και να ελέγξετε ότι η συσκευή εμφανίζεται (ο υπολογιστής σας πρέπει να μπορεί να την προσπελάσει). Εκτελέστε επίσης την εντολή frida-ps -Uia για να ελέγξετε τις εκτελούμενες διεργασίες του τηλεφώνου.

Εγκατάσταση Πελάτη Frida

Εγκαταστήστε τα εργαλεία frida:

pip install frida-tools
pip install frida

Με τον διακομιστή Frida εγκατεστημένο και τη συσκευή να λειτουργεί και συνδεδεμένη, ελέγξτε αν ο πελάτης λειτουργεί:

frida-ls-devices  # List devices
frida-ps -Uia     # Get running processes

Καταγραφή με το Frida

# Functions
## Trace all functions with the word "log" in their name
frida-trace -U <program> -i "*log*"
frida-trace -U <program> -i "*log*" | swift demangle # Demangle names

# Objective-C
## Trace all methods of all classes
frida-trace -U <program> -m "*[* *]"

## Trace all methods with the word "authentication" from classes that start with "NE"
frida-trace -U <program> -m "*[NE* *authentication*]"

# Plug-In
## To hook a plugin that is momentarely executed prepare Frida indicating the ID of the Plugin binary
frida-trace -U -W <if-plugin-bin> -m '*[* *]'

Λήψη όλων των κλάσεων και μεθόδων

  • Αυτόματη συμπλήρωση: Απλά εκτελέστε frida -U <πρόγραμμα>

  • Λήψη όλων των διαθέσιμων κλάσεων (φιλτράρισμα με βάση τη συμβολοσειρά)

/tmp/script.js
// frida -U <program> -l /tmp/script.js

var filterClass = "filterstring";

if (ObjC.available) {
for (var className in ObjC.classes) {
if (ObjC.classes.hasOwnProperty(className)) {
if (!filterClass || className.includes(filterClass)) {
console.log(className);
}
}
}
} else {
console.log("Objective-C runtime is not available.");
}
  • Λήψη όλων των μεθόδων ενός κλάσης (φιλτράρισμα με βάση τη συμβολοσειρά)

/tmp/script.js
// frida -U <program> -l /tmp/script.js

var specificClass = "YourClassName";
var filterMethod = "filtermethod";

if (ObjC.available) {
if (ObjC.classes.hasOwnProperty(specificClass)) {
var methods = ObjC.classes[specificClass].$ownMethods;
for (var i = 0; i < methods.length; i++) {
if (!filterMethod || methods[i].includes(filterClass)) {
console.log(specificClass + ': ' + methods[i]);
}
}
} else {
console.log("Class not found.");
}
} else {
console.log("Objective-C runtime is not available.");
}
  • Καλέστε μια συνάρτηση

// Find the address of the function to call
const func_addr = Module.findExportByName("<Prog Name>", "<Func Name>");
// Declare the function to call
const func = new NativeFunction(
func_addr,
"void", ["pointer", "pointer", "pointer"], {
});

var arg0 = null;

// In this case to call this function we need to intercept a call to it to copy arg0
Interceptor.attach(wg_log_addr, {
onEnter: function(args) {
arg0 = new NativePointer(args[0]);
}
});

// Wait untill a call to the func occurs
while (! arg0) {
Thread.sleep(1);
console.log("waiting for ptr");
}


var arg1 = Memory.allocUtf8String('arg1');
var txt = Memory.allocUtf8String('Some text for arg2');
wg_log(arg0, arg1, txt);

console.log("loaded");

Frida Fuzzing

Frida Stalker

Από τα έγγραφα: Ο Stalker είναι η μηχανή καταγραφής κώδικα του Frida. Επιτρέπει την παρακολούθηση νημάτων, καταγράφοντας κάθε συνάρτηση, κάθε μπλοκ, ακόμα και κάθε εντολή που εκτελείται.

Έχετε ένα παράδειγμα υλοποίησης του Frida Stalker στο https://github.com/poxyran/misc/blob/master/frida-stalker-example.py

Αυτό είναι ένα άλλο παράδειγμα για να συνδεθείτε με το Frida Stalker κάθε φορά που καλείται μια συνάρτηση:

console.log("loading");
const wg_log_addr = Module.findExportByName("<Program>", "<function_name>");
const wg_log = new NativeFunction(
wg_log_addr,
"void", ["pointer", "pointer", "pointer"], {
});

Interceptor.attach(wg_log_addr, {
onEnter: function(args) {
console.log(`logging the following message: ${args[2].readCString()}`);

Stalker.follow({
events: {
// only collect coverage for newly encountered blocks
compile: true,
},
onReceive: function (events) {
const bbs = Stalker.parse(events, {
stringify: false,
annotate: false
});
console.log("Stalker trace of write_msg_to_log: \n" + bbs.flat().map(DebugSymbol.fromAddress).join('\n'));
}
});
},
onLeave: function(retval) {
Stalker.unfollow();
Stalker.flush();  // this is important to get all events
}
});

Αυτό είναι ενδιαφέρον για σκοπούς εντοπισμού σφαλμάτων, αλλά για το fuzzing, το να είναι συνεχώς .follow() και .unfollow() είναι πολύ ανεπαρκές.

fpicker είναι ένα σύνολο εργαλείων fuzzing βασισμένο σε Frida που προσφέρει μια ποικιλία λειτουργιών fuzzing για fuzzing εντός διεργασιών, όπως έναν τρόπο AFL++ ή έναν παθητικό τρόπο ανίχνευσης. Θα πρέπει να λειτουργεί σε όλες τις πλατφόρμες που υποστηρίζονται από το Frida.

# Get fpicker
git clone https://github.com/ttdennis/fpicker
cd fpicker

# Get Frida core devkit and prepare fpicker
wget https://github.com/frida/frida/releases/download/16.1.4/frida-core-devkit-16.1.4-[yourOS]-[yourarchitecture].tar.xz
# e.g. https://github.com/frida/frida/releases/download/16.1.4/frida-core-devkit-16.1.4-macos-arm64.tar.xz
tar -xf ./*tar.xz
cp libfrida-core.a libfrida-core-[yourOS].a #libfrida-core-macos.a

# Install fpicker
make fpicker-[yourOS] # fpicker-macos
# This generates ./fpicker

# Install radamsa (fuzzer generator)
brew install radamsa
  • Προετοιμασία του συστήματος αρχείων (FS):

# From inside fpicker clone
mkdir -p examples/wg-log # Where the fuzzing script will be
mkdir -p examples/wg-log/out # For code coverage and crashes
mkdir -p examples/wg-log/in # For starting inputs

# Create at least 1 input for the fuzzer
echo Hello World > examples/wg-log/in/0
  • Σενάριο Fuzzer (παραδείγματα/wg-log/myfuzzer.js):

παραδείγματα/wg-log/myfuzzer.js
// Import the fuzzer base class
import { Fuzzer } from "../../harness/fuzzer.js";

class WGLogFuzzer extends Fuzzer {

constructor() {
console.log("WGLogFuzzer constructor called")

// Get and declare the function we are going to fuzz
var wg_log_addr = Module.findExportByName("<Program name>", "<func name to fuzz>");
var wg_log_func = new NativeFunction(
wg_log_addr,
"void", ["pointer", "pointer", "pointer"], {
});

// Initialize the object
super("<Program nane>", wg_log_addr, wg_log_func);
this.wg_log_addr = wg_log_addr; // We cannot use "this" before calling "super"

console.log("WGLogFuzzer in the middle");

// Prepare the second argument to pass to the fuzz function
this.tag = Memory.allocUtf8String("arg2");

// Get the first argument we need to pass from a call to the functino we want to fuzz
var wg_log_global_ptr = null;
console.log(this.wg_log_addr);
Interceptor.attach(this.wg_log_addr, {
onEnter: function(args) {
console.log("Entering in the function to get the first argument");
wg_log_global_ptr = new NativePointer(args[0]);
}
});

while (! wg_log_global_ptr) {
Thread.sleep(1)
}
this.wg_log_global_ptr = wg_log_global_ptr;
console.log("WGLogFuzzer prepare ended")
}


// This function is called by the fuzzer with the first argument being a pointer into memory
// where the payload is stored and the second the length of the input.
fuzz(payload, len) {
// Get a pointer to payload being a valid C string (with a null byte at the end)
var payload_cstring = payload.readCString(len);
this.payload = Memory.allocUtf8String(payload_cstring);

// Debug and fuzz
this.debug_log(this.payload, len);
// Pass the 2 first arguments we know the function needs and finally the payload to fuzz
this.target_function(this.wg_log_global_ptr, this.tag, this.payload);
}
}

const f = new WGLogFuzzer();
rpc.exports.fuzzer = f;
  • Μεταγλωττίστε το fuzzer:

# From inside fpicker clone
## Compile from "myfuzzer.js" to "harness.js"
frida-compile examples/wg-log/myfuzzer.js -o harness.js
  • Καλέστε το fuzzer fpicker χρησιμοποιώντας το radamsa:

# Indicate fpicker to fuzz a program with the harness.js script and which folders to use
fpicker -v --fuzzer-mode active -e attach -p <Program to fuzz> -D usb -o examples/wg-log/out/ -i examples/wg-log/in/ -f harness.js --standalone-mutator cmd --mutator-command "radamsa"
# You can find code coverage and crashes in examples/wg-log/out/

Σε αυτήν την περίπτωση δεν επανεκκινούμε την εφαρμογή ή επαναφέρουμε την κατάσταση μετά από κάθε φορτωτή. Έτσι, αν το Frida βρει ένα σφάλμα, τα επόμενα δεδομένα εισόδου μετά από αυτόν τον φορτωτή ενδέχεται επίσης να καταρρεύσουν την εφαρμογή (επειδή η εφαρμογή βρίσκεται σε μη σταθερή κατάσταση), ακόμα κι αν η είσοδος δεν θα έπρεπε να καταρρεύσει την εφαρμογή.

Επιπλέον, το Frida θα συνδεθεί με τα σήματα εξαιρέσεων του iOS, οπότε όταν το Frida βρει ένα σφάλμα, πιθανώς δεν θα δημιουργηθούν αναφορές κατάρρευσης του iOS.

Για να αποτρέψουμε αυτό, για παράδειγμα, θα μπορούσαμε να επανεκκινήσουμε την εφαρμογή μετά από κάθε κατάρρευση του Frida.

Καταγραφές & Καταρρεύσεις

Μπορείτε να ελέγξετε τη κονσόλα macOS ή το log cli για να ελέγξετε τα αρχεία καταγραφής του macOS. Μπορείτε επίσης να ελέγξετε τα αρχεία καταγραφής από το iOS χρησιμοποιώντας το idevicesyslog. Ορισμένα αρχεία καταγραφής θα παραλείπουν πληροφορίες προσθέτοντας <private>. Για να εμφανιστούν όλες οι πληροφορίες, πρέπει να εγκαταστήσετε κάποιο προφίλ από https://developer.apple.com/bug-reporting/profiles-and-logs/ για να ενεργοποιήσετε αυτές τις ιδιωτικές πληροφορίες.

Αν δεν ξέρετε τι να κάνετε:

vim /Library/Preferences/Logging/com.apple.system.logging.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Enable-Private-Data</key>
<true/>
</dict>
</plist>

killall -9 logd

Μπορείτε να ελέγξετε τα κρασαρίσματα σε:

  • iOS

  • Ρυθμίσεις → Απορρήτου → Αναλύσεις & Βελτιώσεις → Δεδομένα Ανάλυσης

  • /private/var/mobile/Library/Logs/CrashReporter/

  • macOS:

  • /Library/Logs/DiagnosticReports/

  • ~/Library/Logs/DiagnosticReports

Το iOS αποθηκεύει μόνο 25 κρασαρίσματα της ίδιας εφαρμογής, οπότε πρέπει να τα καθαρίσετε διαφορετικά το iOS θα σταματήσει να δημιουργεί κρασαρίσματα.

Οδηγοί Frida Android

Αναφορές

WhiteIntel είναι μια μηχανή αναζήτησης που τροφοδοτείται από το dark web και προσφέρει δωρεάν λειτουργίες για να ελέγξετε αν μια εταιρεία ή οι πελάτες της έχουν διαρρεύσει από κλέφτες κακόβουλων λογισμικών.

Ο κύριος στόχος του WhiteIntel είναι η καταπολέμηση των αποκλεισμών λογαριασμών και των επιθέσεων ransomware που προκύπτουν από κακόβουλα λογισμικά που κλέβουν πληροφορίες.

Μπορείτε να ελέγξετε την ιστοσελίδα τους και να δοκιμάσετε τη μηχανή τους δωρεάν στο:

Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι υποστήριξης του HackTricks:

Last updated