pip install frida
pip install frida-tools
Fridump3를 깃허브에서 다운/클론 받아 로컬에 저장합니다
foremost를 homebrew 등의 방법으로 zsh에서 실행할 수 있게 설정합니다.
checkra1n (unc0ver, dopamine 등을 사용하셔도 무방합니다)
C-Lightning 케이블로 DFU 모드 진입이 불가능하다는 이슈가 있습니다
A-Lightning 케이블로 진행해주세요
웹뷰 혹은 사파리 브라우저의 내용을 보기 위해서는 com.apple.WebKit.WebContent를 덤프 떠야 합니다
12.5.7에서는 성공하는 것을 확인하였으나 14.2, 15.0에서는 injection 오류 혹은 unexpected early end-of-stream 가 발생합니다.
애플 측에서 막아 놓은 것으로 추정하고 있습니다.
(https://github.com/frida/frida/issues/1865)
파이썬으로 작성되었습니다
foremost를 실행하면서 temp 디렉토리에서 옮기는 이유는 와일드카드(/*) 형식으로 파일을 전체 지정하면 output 디렉토리가 제대로 지정되지 않아서 파일 하나하나 읽어와야 되기 때문입니다
foremost는 output 디렉토리가 비어있지 않으면 에러가 발생합니다
fridump3.py 가 저장된 경로를 수정해주세요
import os
import subprocess
import argparse
from datetime import datetime
import sys
import shutil
def dumpUSBMemory(pid, outputDirectory):
options = [
'-u',
'-o', outputDirectory,
'-s',
]
dumpMemory(pid, options)
def dumpPCMemory(pid, outputDirectory):
options = [
'-o', outputDirectory,
'-s',
]
dumpMemory(pid, options)
def dumpMemory(pid, options):
print("\n<Dump out memory RUNNING>\n")
command = [
sys.executable, '-u',
'./fridump3-master/fridump3.py' # ⛑️ 경로체크!!
] + options + [pid]
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
for line in process.stdout:
print(line, end='')
for line in process.stderr:
print(line, end='')
return_code = process.wait()
if return_code != 0:
print(f"Fridump3 exited with error code {return_code}")
print("\n<Dump out memory DONE>\n")
def extractFilesFromBinary(binaryFileDirectory):
print("\n<Extract files from dump data RUNNING>\n")
finalOutputDirectory = f'{binaryFileDirectory}/foremost_output'
tempOutputDirectory = f'{binaryFileDirectory}/foremost_temp_output'
fileNames = os.listdir(binaryFileDirectory)
os.mkdir(finalOutputDirectory)
for fileName in fileNames:
command = [
'foremost',
'-i', f'{binaryFileDirectory}/{fileName}',
'-o', tempOutputDirectory,
]
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
for line in process.stdout:
print(line, end='')
for line in process.stderr:
print(line, end='')
return_code = process.wait()
if return_code != 0:
print(f"foremost exited with error code: {return_code}, file name: {fileName}")
filePathsInTempDirectory = filePathsInDirectory(tempOutputDirectory)
for filePath in filePathsInTempDirectory:
if 'audit.txt' in filePath: continue
moveFile(filePath, finalOutputDirectory)
shutil.rmtree(tempOutputDirectory)
print("\n<Extract files from dump data DONE>\n")
def moveFile(path, destination):
fileName = os.path.basename(path)
shutil.move(path, f'{destination}/{fileName}')
def filePathsInDirectory(path):
filePaths = []
for entry in os.listdir(path):
fullPath = os.path.join(path, entry)
if os.path.isdir(fullPath):
filePaths = filePaths + filePathsInDirectory(fullPath)
else:
filePaths.append(fullPath)
return filePaths
def getPIDsFromUSB(appName):
return getPIDs(appName, ['-U'])
def getPIDsFromPC(appName):
return getPIDs(appName, [])
def getPIDs(appName, options):
proc1 = subprocess.Popen(['frida-ps'] + options, stdout=subprocess.PIPE)
proc2 = subprocess.Popen(['grep', appName], stdin=proc1.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc1.stdout.close()
out, _ = proc2.communicate()
pids = list(map(lambda x: x.split()[0], out.decode().splitlines()))
return pids
def getFormattedDate():
now = datetime.now()
return now.strftime("%Y%m%d%H%M%S")
def parseArguments():
parser = argparse.ArgumentParser(description="Process some arguments.")
parser.add_argument('args', nargs='+', help='Arguments passed from the shell script')
# Parse the arguments
args = parser.parse_args()
# Print the arguments
print("Arguments received from shell script:", args.args)
return args.args
# ⛑️⛑️⛑️⛑️ MAIN ⛑️⛑️⛑️⛑️
if __name__ == "__main__":
[appNameToDump, dumpOutputBaseDirectory, platform] = parseArguments()
if platform not in ["usb", "pc"]:
print("platform is only allowed for usb & pc. Case sensitive")
exit()
if os.path.isdir(dumpOutputBaseDirectory) == False:
print(dumpOutputBaseDirectory," is not directory")
exit()
print("appNameToDump: ", appNameToDump)
print("dumpOutputBaseDirectory: ", dumpOutputBaseDirectory)
print("platform: ", platform)
if platform == "usb":
pids = getPIDsFromUSB(appNameToDump)
elif platform == "pc":
pids = getPIDsFromPC(appNameToDump)
if len(pids) == 0:
print(f"NO pid that matches to {appNameToDump}")
for pid in pids:
print("PID for {0}: {1}".format(appNameToDump, pid))
dumpOutputDirectory = f"{dumpOutputBaseDirectory}/{appNameToDump}_{getFormattedDate()}_{pid}_dumpOutput"
os.mkdir(dumpOutputDirectory)
if platform == "usb":
dumpUSBMemory(pid, dumpOutputDirectory)
elif platform == "pc":
dumpPCMemory(pid, dumpOutputDirectory)
extractFilesFromBinary(dumpOutputDirectory)
print("### PROCESS DONE ###")
exit()
python {파일이름}.py {앱이름} {덤프파일_저장할_디렉토리} usb
python {파일이름}.py {앱이름} {덤프파일_저장할_디렉토리} pc