iOS Frida Configuration

htARTE (HackTricks AWS Red Team Expert)를 통해 AWS 해킹을 처음부터 전문가까지 배우세요

HackTricks를 지원하는 다른 방법:

WhiteIntel다크 웹을 활용한 검색 엔진으로, 회사나 고객이 스틸러 악성 소프트웨어에 의해 침해되었는지 무료 기능을 제공합니다.

WhiteIntel의 주요 목표는 정보 도난 악성 소프트웨어로 인한 계정 탈취 및 랜섬웨어 공격을 막는 것입니다.

그들의 웹사이트를 확인하고 무료로 엔진을 시도해 볼 수 있습니다:


Frida 설치

Jailbroken 장치에 Frida를 설치하는 단계:

  1. Cydia/Sileo 앱을 엽니다.

  2. 관리 -> 소스 -> 편집 -> 추가로 이동합니다.

  3. URL로 "https://build.frida.re"를 입력합니다.

  4. 새로 추가된 Frida 소스로 이동합니다.

  5. Frida 패키지를 설치합니다.

Corellium을 사용하는 경우 https://github.com/frida/frida/releases에서 Frida 릴리스를 다운로드해야 합니다 (frida-gadget-[yourversion]-ios-universal.dylib.gz) 및 Frida가 요청하는 dylib 위치로 압축을 풀고 복사해야 합니다. 예: /Users/[youruser]/.cache/frida/gadget-ios.dylib

설치 후 PC에서 frida-ls-devices 명령을 사용하여 장치가 나타나는지 확인할 수 있습니다 (PC가 액세스할 수 있어야 함). 또한 **frida-ps -Uia**를 실행하여 폰의 실행 중인 프로세스를 확인할 수 있습니다.

Jailbroken 장치 없이 Frida 및 앱 패치 없이

앱을 패치하지 않고 비 Jailbroken 장치에서 Frida를 사용하는 방법에 대한 블로그 포스트를 확인하세요: https://mrbypass.medium.com/unlocking-potential-exploring-frida-objection-on-non-jailbroken-devices-without-application-ed0367a84f07

Frida 클라이언트 설치

frida 도구를 설치하세요:

pip install frida-tools
pip install frida

Frida 서버가 설치되어 있고 장치가 실행되고 연결된 상태에서 클라이언트가 작동하는지 확인하십시오:

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

프리다 트레이스

# 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.");
}
  • 클래스모든 메소드 가져오기 (문자열로 필터링)

// 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
}
});

디버깅 목적으로는 흥미로울 수 있지만 퍼징을 위해서는 계속해서 .follow() 및 **.unfollow()**를 해야 하기 때문에 매우 비효율적입니다.

fpicker은 프로세스 내 퍼징을 위한 다양한 퍼징 모드인 AFL++ 모드 또는 패시브 추적 모드와 같은 옵션을 제공하는 Frida 기반의 퍼징 스위트입니다. 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
  • 파일 시스템 준비:

# 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 스크립트 (examples/wg-log/myfuzzer.js):

examples/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;
  • 퍼저 컴파일하기:

# From inside fpicker clone
## Compile from "myfuzzer.js" to "harness.js"
frida-compile examples/wg-log/myfuzzer.js -o harness.js
  • **radamsa**를 사용하여 **fpicker**를 호출합니다:

# 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 충돌 후에 앱을 다시 시작할 수 있습니다.

Logs & Crashes

macOS 콘솔이나 log cli를 사용하여 macOS 로그를 확인할 수 있습니다. **idevicesyslog**를 사용하여 iOS의 로그도 확인할 수 있습니다. 일부 로그는 **<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 튜토리얼

pageFrida Tutorial

참고 자료

WhiteIntel다크 웹을 활용한 검색 엔진으로, 회사나 그 고객이 스틸러 악성 코드에 의해 침해당했는지 확인할 수 있는 무료 기능을 제공합니다.

WhiteIntel의 주요 목표는 정보를 도난당한 악성 코드로 인한 계정 탈취 및 랜섬웨어 공격을 막는 것입니다.

그들의 웹사이트를 방문하여 무료로 엔진을 시도해 볼 수 있습니다:

**htARTE (HackTricks AWS Red Team Expert)**와 함께 **제로**부터 **히어로**까지 AWS 해킹을 배우세요!

HackTricks를 지원하는 다른 방법:

Last updated