Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

迁移MonkeyDev到Xcode13+,不兼容Xcode 13以下 #325

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
389 changes: 389 additions & 0 deletions Resource/dump.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,389 @@
Module.ensureInitialized('Foundation');

var O_RDONLY = 0;
var O_WRONLY = 1;
var O_RDWR = 2;
var O_CREAT = 512;

var SEEK_SET = 0;
var SEEK_CUR = 1;
var SEEK_END = 2;

function allocStr(str) {
return Memory.allocUtf8String(str);
}

function putStr(addr, str) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.writeUtf8String(addr, str);
}

function getByteArr(addr, l) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.readByteArray(addr, l);
}

function getU8(addr) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.readU8(addr);
}

function putU8(addr, n) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.writeU8(addr, n);
}

function getU16(addr) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.readU16(addr);
}

function putU16(addr, n) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.writeU16(addr, n);
}

function getU32(addr) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.readU32(addr);
}

function putU32(addr, n) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.writeU32(addr, n);
}

function getU64(addr) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.readU64(addr);
}

function putU64(addr, n) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.writeU64(addr, n);
}

function getPt(addr) {
if (typeof addr == "number") {
addr = ptr(addr);
}
return Memory.readPointer(addr);
}

function putPt(addr, n) {
if (typeof addr == "number") {
addr = ptr(addr);
}
if (typeof n == "number") {
n = ptr(n);
}
return Memory.writePointer(addr, n);
}

function malloc(size) {
return Memory.alloc(size);
}

function getExportFunction(type, name, ret, args) {
var nptr;
nptr = Module.findExportByName(null, name);
if (nptr === null) {
console.log("cannot find " + name);
return null;
} else {
if (type === "f") {
var funclet = new NativeFunction(nptr, ret, args);
if (typeof funclet === "undefined") {
console.log("parse error " + name);
return null;
}
return funclet;
} else if (type === "d") {
var datalet = Memory.readPointer(nptr);
if (typeof datalet === "undefined") {
console.log("parse error " + name);
return null;
}
return datalet;
}
}
}

var NSSearchPathForDirectoriesInDomains = getExportFunction("f", "NSSearchPathForDirectoriesInDomains", "pointer", ["int", "int", "int"]);
var wrapper_open = getExportFunction("f", "open", "int", ["pointer", "int", "int"]);
var read = getExportFunction("f", "read", "int", ["int", "pointer", "int"]);
var write = getExportFunction("f", "write", "int", ["int", "pointer", "int"]);
var lseek = getExportFunction("f", "lseek", "int64", ["int", "int64", "int"]);
var close = getExportFunction("f", "close", "int", ["int"]);
var remove = getExportFunction("f", "remove", "int", ["pointer"]);
var access = getExportFunction("f", "access", "int", ["pointer", "int"]);
var dlopen = getExportFunction("f", "dlopen", "pointer", ["pointer", "int"]);

function getDocumentDir() {
var NSDocumentDirectory = 9;
var NSUserDomainMask = 1;
var npdirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, 1);
return ObjC.Object(npdirs).objectAtIndex_(0).toString();
}

function open(pathname, flags, mode) {
if (typeof pathname == "string") {
pathname = allocStr(pathname);
}
return wrapper_open(pathname, flags, mode);
}

var modules = null;
function getAllAppModules() {
modules = new Array();
var tmpmods = Process.enumerateModulesSync();
for (var i = 0; i < tmpmods.length; i++) {
if (tmpmods[i].path.indexOf(".app") != -1) {
modules.push(tmpmods[i]);
}
}
return modules;
}

var FAT_MAGIC = 0xcafebabe;
var FAT_CIGAM = 0xbebafeca;
var MH_MAGIC = 0xfeedface;
var MH_CIGAM = 0xcefaedfe;
var MH_MAGIC_64 = 0xfeedfacf;
var MH_CIGAM_64 = 0xcffaedfe;
var LC_SEGMENT = 0x1;
var LC_SEGMENT_64 = 0x19;
var LC_ENCRYPTION_INFO = 0x21;
var LC_ENCRYPTION_INFO_64 = 0x2C;

function pad(str, n) {
return Array(n-str.length+1).join("0")+str;
}

function swap32(value) {
value = pad(value.toString(16),8)
var result = "";
for(var i = 0; i < value.length; i=i+2){
result += value.charAt(value.length - i - 2);
result += value.charAt(value.length - i - 1);
}
return parseInt(result,16)
}

function dumpModule(name) {
if (modules == null) {
modules = getAllAppModules();
}

var targetmod = null;
for (var i = 0; i < modules.length; i++) {
if (modules[i].path.indexOf(name) != -1) {
targetmod = modules[i];
break;
}
}
if (targetmod == null) {
console.log("Cannot find module");
return;
}
var modbase = modules[i].base;
var modsize = modules[i].size;
var newmodname = modules[i].name;
var newmodpath = getDocumentDir() + "/" + newmodname + ".fid";
var oldmodpath = modules[i].path;


if(!access(allocStr(newmodpath),0)){
remove(allocStr(newmodpath));
}

var fmodule = open(newmodpath, O_CREAT | O_RDWR, 0);
var foldmodule = open(oldmodpath, O_RDONLY, 0);

if (fmodule == -1 || foldmodule == -1) {
console.log("Cannot open file" + newmodpath);
return;
}

var is64bit = false;
var size_of_mach_header = 0;
var magic = getU32(modbase);
var cur_cpu_type = getU32(modbase.add(4));
var cur_cpu_subtype = getU32(modbase.add(8));
if (magic == MH_MAGIC || magic == MH_CIGAM) {
is64bit = false;
size_of_mach_header = 28;
}else if (magic == MH_MAGIC_64 || magic == MH_CIGAM_64) {
is64bit = true;
size_of_mach_header = 32;
}

var BUFSIZE = 4096;
var buffer = malloc(BUFSIZE);

read(foldmodule, buffer, BUFSIZE);

var fileoffset = 0;
var filesize = 0;
magic = getU32(buffer);
if(magic == FAT_CIGAM || magic == FAT_MAGIC){
var off = 4;
var archs = swap32(getU32(buffer.add(off)));
for (var i = 0; i < archs; i++) {
var cputype = swap32(getU32(buffer.add(off + 4)));
var cpusubtype = swap32(getU32(buffer.add(off + 8)));
if(cur_cpu_type == cputype && cur_cpu_subtype == cpusubtype){
fileoffset = swap32(getU32(buffer.add(off + 12)));
filesize = swap32(getU32(buffer.add(off + 16)));
break;
}
off += 20;
}

if(fileoffset == 0 || filesize == 0)
return;

lseek(fmodule, 0, SEEK_SET);
lseek(foldmodule, fileoffset, SEEK_SET);
for(var i = 0; i < parseInt(filesize / BUFSIZE); i++) {
read(foldmodule, buffer, BUFSIZE);
write(fmodule, buffer, BUFSIZE);
}
if(filesize % BUFSIZE){
read(foldmodule, buffer, filesize % BUFSIZE);
write(fmodule, buffer, filesize % BUFSIZE);
}
}else{
var readLen = 0;
lseek(foldmodule, 0, SEEK_SET);
lseek(fmodule, 0, SEEK_SET);
while(readLen = read(foldmodule, buffer, BUFSIZE)) {
write(fmodule, buffer, readLen);
}
}

var ncmds = getU32(modbase.add(16));
var off = size_of_mach_header;
var offset_cryptid = -1;
var crypt_off = 0;
var crypt_size = 0;
var segments = [];
for (var i = 0; i < ncmds; i++) {
var cmd = getU32(modbase.add(off));
var cmdsize = getU32(modbase.add(off + 4));
if (cmd == LC_ENCRYPTION_INFO || cmd == LC_ENCRYPTION_INFO_64) {
offset_cryptid = off + 16;
crypt_off = getU32(modbase.add(off + 8));
crypt_size = getU32(modbase.add(off + 12));
}
off += cmdsize;
}

if (offset_cryptid != -1) {
var tpbuf = malloc(8);
putU64(tpbuf, 0);
lseek(fmodule, offset_cryptid, SEEK_SET);
write(fmodule, tpbuf, 4);
lseek(fmodule, crypt_off, SEEK_SET);
write(fmodule, modbase.add(crypt_off), crypt_size);
}

close(fmodule);
close(foldmodule);
return newmodpath
}

function loadAllDynamicLibrary(app_path) {
var defaultManager = ObjC.classes.NSFileManager.defaultManager();
var errorPtr = Memory.alloc(Process.pointerSize);
Memory.writePointer(errorPtr, NULL);
var filenames = defaultManager.contentsOfDirectoryAtPath_error_(app_path, errorPtr);
for (var i = 0, l = filenames.count(); i < l; i++) {
var file_name = filenames.objectAtIndex_(i);
var file_path = app_path.stringByAppendingPathComponent_(file_name);
if (file_name.hasSuffix_(".framework")) {
var bundle = ObjC.classes.NSBundle.bundleWithPath_(file_path);
if (bundle.isLoaded()) {
console.log("[frida-ios-dump]: " + file_name + " has been loaded. ");
} else {
if (bundle.load()) {
console.log("[frida-ios-dump]: Load " + file_name + " success. ");
} else {
console.log("[frida-ios-dump]: Load " + file_name + " failed. ");
}
}
} else if (file_name.hasSuffix_(".bundle") ||
file_name.hasSuffix_(".momd") ||
file_name.hasSuffix_(".strings") ||
file_name.hasSuffix_(".appex") ||
file_name.hasSuffix_(".app") ||
file_name.hasSuffix_(".lproj") ||
file_name.hasSuffix_(".storyboardc")) {
continue;
} else {
var isDirPtr = Memory.alloc(Process.pointerSize);
Memory.writePointer(isDirPtr,NULL);
defaultManager.fileExistsAtPath_isDirectory_(file_path, isDirPtr);
if (Memory.readPointer(isDirPtr) == 1) {
loadAllDynamicLibrary(file_path);
} else {
if (file_name.hasSuffix_(".dylib")) {
var is_loaded = 0;
for (var j = 0; j < modules.length; j++) {
if (modules[j].path.indexOf(file_name) != -1) {
is_loaded = 1;
console.log("[frida-ios-dump]: " + file_name + " has been dlopen.");
break;
}
}

if (!is_loaded) {
if (dlopen(allocStr(file_path.UTF8String()), 9)) {
console.log("[frida-ios-dump]: dlopen " + file_name + " success. ");
} else {
console.log("[frida-ios-dump]: dlopen " + file_name + " failed. ");
}
}
}
}
}
}
}

function handleMessage(message) {
modules = getAllAppModules();
var app_path = ObjC.classes.NSBundle.mainBundle().bundlePath();
loadAllDynamicLibrary(app_path);
// start dump
modules = getAllAppModules();
for (var i = 0; i < modules.length; i++) {
console.log("start dump " + modules[i].path);
var result = dumpModule(modules[i].path);
send({ dump: result, path: modules[i].path});
}
send({app: app_path.toString()});
send({done: "ok"});
recv(handleMessage);
}

recv(handleMessage);
Loading