mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-18 06:44:46 -07:00
Add MachoManiac
This commit is contained in:
parent
04c0b7aeae
commit
50b1c46678
34 changed files with 5269 additions and 0 deletions
4
helpers/macho/index.js
Normal file
4
helpers/macho/index.js
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import MachoParser from './macho.js'
|
||||
|
||||
|
||||
export default MachoParser
|
||||
3543
helpers/macho/jquery-blob.js
vendored
Normal file
3543
helpers/macho/jquery-blob.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
13
helpers/macho/macho.constants.js
Normal file
13
helpers/macho/macho.constants.js
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
export let SECTION_ATTRIBUTES_USR = 0xff000000;
|
||||
export let S_ATTR_PURE_INSTRUCTIONS = 0x80000000;
|
||||
export let SECTION_ATTRIBUTES_SYS = 0x00ffff00;
|
||||
export let S_ATTR_SOME_INSTRUCTIONS = 0x0000400;
|
||||
export let S_ATTR_EXT_RELOC = 0x00000200;
|
||||
export let S_ATTR_LOC_RELOC = 0x00000100;
|
||||
|
||||
export let uint128_t = 16;
|
||||
export let uint64_t = 8;
|
||||
export let uint32_t = 4;
|
||||
export let uint16_t = 2;
|
||||
export let uint8_t = 1;
|
||||
|
||||
134
helpers/macho/macho.cpu.js
Normal file
134
helpers/macho/macho.cpu.js
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
//Global Constants
|
||||
var CPU_TYPES = [];
|
||||
var CPUSubTypeARM = [];
|
||||
|
||||
let CPU_ARCH_CONST = {
|
||||
MASK: 0x01000000,
|
||||
ABI64: 0xff000000,
|
||||
toString: function() {
|
||||
JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
let CPU_TYPE = {
|
||||
ANY: -1,
|
||||
VAX: 1,
|
||||
MC680: 6,
|
||||
X86: 7,
|
||||
MIPS: 8,
|
||||
MC98000: 10,
|
||||
HPPA: 11,
|
||||
ARM: 12,
|
||||
ARM64: 16777228,
|
||||
MC88000: 13,
|
||||
SPARC: 14,
|
||||
I860: 15,
|
||||
POWERPC: 18,
|
||||
POWERPC64: 16777234,
|
||||
DESCRIPTION: function(search) {
|
||||
let result = CPU_TYPES[search];
|
||||
return (result != undefined) ? result : search;
|
||||
},
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
CPU_TYPES[CPU_TYPE.ANY] = "Any";
|
||||
CPU_TYPES[CPU_TYPE.VAX] = "VAX";
|
||||
CPU_TYPES[CPU_TYPE.MC680] = "MC680";
|
||||
CPU_TYPE[CPU_TYPE.HPPA] = "HPPA";
|
||||
CPU_TYPES[CPU_TYPE.ARM] = "ARM";
|
||||
CPU_TYPES[CPU_TYPE.ARM64] = "ARM64";
|
||||
CPU_TYPES[CPU_TYPE.X86] = "X86";
|
||||
CPU_TYPES[CPU_TYPE.I860] = "I860";
|
||||
CPU_TYPES[CPU_TYPE.MIPS] = "Mips";
|
||||
CPU_TYPES[CPU_TYPE.MC98000] = "MC98000";
|
||||
CPU_TYPES[CPU_TYPE.SPARC] = "Sparc";
|
||||
CPU_TYPES[CPU_TYPE.POWERPC] = "Power PC";
|
||||
CPU_TYPES[CPU_TYPE.POWERPC64] = "Power PC 64-bit";
|
||||
|
||||
let CPU_SUB_TYPE = {
|
||||
ARM: {
|
||||
MULTIPLE: -1,
|
||||
ALL: 0,
|
||||
ARM_A500_ARCH: 1,
|
||||
ARM_A500: 2,
|
||||
ARM_A440: 3,
|
||||
ARM_M4: 4,
|
||||
V4T: 5,
|
||||
V6: 6,
|
||||
V5TEJ: 7,
|
||||
XSCALE: 8,
|
||||
V7: 9,
|
||||
V7F: 10,
|
||||
V7S: 11,
|
||||
V7K: 12,
|
||||
V8: 13,
|
||||
V6M: 14,
|
||||
V7M: 15,
|
||||
V7EM: 16,
|
||||
DESCRIPTION: function(search) {
|
||||
|
||||
|
||||
let result = CPUSubTypeARM[search];
|
||||
return (result != undefined) ? result : search;
|
||||
},
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
},
|
||||
ARM64: {
|
||||
MULTIPLE: -1,
|
||||
ALL: 0,
|
||||
V8: 1,
|
||||
DESCRIPTION: function(search) {
|
||||
var CPUSubTypeARM64 = [];
|
||||
CPUSubTypeARM64[CPU_SUB_TYPE.ARM64.ALL] = 'all';
|
||||
let result = CPUSubTypeARM64[search];
|
||||
return (result != undefined) ? result : search;
|
||||
},
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
},
|
||||
POWERPC64: {
|
||||
MULTIPLE: -1,
|
||||
POWERPC_ALL: 0,
|
||||
POWERPC_601: 1,
|
||||
POWERPC_602: 2,
|
||||
POWERPC_603: 3,
|
||||
POWERPC_603e: 4,
|
||||
POWERPC_603ev: 5,
|
||||
POWERPC_604: 6,
|
||||
POWERPC_604e: 7,
|
||||
POWERPC_620: 8,
|
||||
POWERPC_750: 9,
|
||||
POWERPC_7400: 10,
|
||||
POWERPC_7450: 11,
|
||||
POWERPC_970: 100,
|
||||
POWERPC_ALL_LIB64: 2147483648,
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
},
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.ALL] = 'all';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.V4T] = 'v4t';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.V6] = 'v6';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.V5] = 'v5';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.XSCALE] = 'xscale';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.V7] = 'v7';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.V7F] = 'v7f';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.V7S] = 'v7s';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.V7K] = 'v7k';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.V6M] = 'v6m';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.V7M] = 'v7m';
|
||||
CPUSubTypeARM[CPU_SUB_TYPE.ARM.V7EM] = 'v7em';
|
||||
|
||||
|
||||
export { CPU_TYPES, CPUSubTypeARM, CPU_ARCH_CONST, CPU_TYPE, CPU_SUB_TYPE }
|
||||
10
helpers/macho/macho.cstr.js
Normal file
10
helpers/macho/macho.cstr.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
var Cstr = function Cstr(buf) {
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
var cstr = '';
|
||||
for(var i = 0; i < buf.length; i++) {
|
||||
cstr += String.fromCharCode(buf[i]);
|
||||
}
|
||||
return cstr;
|
||||
};
|
||||
72
helpers/macho/macho.dylib.js
Normal file
72
helpers/macho/macho.dylib.js
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
var Dylib = function Dylib(name, timestamp, current_version, compatibility_version) {
|
||||
this.name = name || 0x00000000;
|
||||
this.timestamp = timestamp || 0x00000000;
|
||||
this.current_version = current_version || 0x00000000;
|
||||
this.compatibility_version = compatibility_version || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
|
||||
var DylibCommand = function DylibCommand(cmd, cmdsize, dylib) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.dylib = dylib || new Dylib(); //needs better input validation
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
|
||||
var DylibTableOfContents = function DylibTableOfContents(symbol_index, module_index) {
|
||||
this.symbol_index = symbol_index || 0x00000000;
|
||||
this.module_index = module_index || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
|
||||
var DylibModule = function DylibModule(module_name, iextdefsym, nextdefsym, irefsym, nrefsym, ilocalsym, nlocalsym, iextrel, nextrel, iinit_iterm, ninit_nterm, objc_module_info_addr, objc_module_info_size) {
|
||||
this.module_name = module_name || 0x00000000;
|
||||
this.iextdefsym = iextdefsym || 0x00000000;
|
||||
this.nextdefsym = nextdefsym || 0x00000000;
|
||||
this.irefsym = irefsym || 0x00000000;
|
||||
this.nrefsym = nrefsym || 0x00000000;
|
||||
this.ilocalsym = ilocalsym || 0x00000000;
|
||||
this.nlocalsym = nlocalsym || 0x00000000;
|
||||
this.iextrel = iextrel || 0x00000000;
|
||||
this.nextrel = nextrel || 0x00000000;
|
||||
this.iinit_iterm = iinit_iterm || 0x00000000;
|
||||
this.ninit_nterm = ninit_nterm || 0x00000000;
|
||||
this.objc_module_info_addr = objc_module_info_addr || 0x00000000;
|
||||
this.objc_module_info_size = objc_module_info_size || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
|
||||
var DylibModule64 = function DylibModule64(module_name, iextdefsym, nextdefsym, irefsym, nrefsym, ilocalsym, nlocalsym, iextrel, nextrel, iinit_iterm, ninit_nterm, objc_module_info_addr, objc_module_info_size) {
|
||||
this.module_name = module_name || 0x00000000;
|
||||
this.iextdefsym = iextdefsym || 0x00000000;
|
||||
this.nextdefsym = nextdefsym || 0x00000000;
|
||||
this.irefsym = irefsym || 0x00000000;
|
||||
this.nrefsym = nrefsym || 0x00000000;
|
||||
this.ilocalsym = ilocalsym || 0x00000000;
|
||||
this.nlocalsym = nlocalsym || 0x00000000;
|
||||
this.iextrel = iextrel || 0x00000000;
|
||||
this.nextrel = nextrel || 0x00000000;
|
||||
this.iinit_iterm = iinit_iterm || 0x00000000;
|
||||
this.ninit_nterm = ninit_nterm || 0x00000000;
|
||||
this.objc_module_info_addr = objc_module_info_addr || 0x00000000;
|
||||
this.objc_module_info_size = objc_module_info_size || 0x0000000000000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
|
||||
var DylibReference = {
|
||||
isym:24,
|
||||
flags:8,
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
7
helpers/macho/macho.dylinker.js
Normal file
7
helpers/macho/macho.dylinker.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
var DylinkerCommand = function DylinkerCommand(cmd, cmdsize) {
|
||||
this.cmd = 0x00000000;
|
||||
this.cmdsize = 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
73
helpers/macho/macho.file.js
Normal file
73
helpers/macho/macho.file.js
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
var FILE_TYPES = [];
|
||||
var FILE_FLAGS = [];
|
||||
|
||||
|
||||
/*
|
||||
@Class FILE_TYPE
|
||||
|
||||
@Description
|
||||
File Type is the class for identifying what MACH-O file is being dealed with.
|
||||
*/
|
||||
let FILE_TYPE = {
|
||||
MH_OBJECT: 0x1, /* relocatable object file */
|
||||
MH_EXECUTE: 0x2, /* demand paged executable file */
|
||||
MH_FVMLIB: 0x3, /* fixed VM shared library file */
|
||||
MH_CORE: 0x4, /* core file */
|
||||
MH_PRELOAD: 0x5, /* preloaded executable file */
|
||||
MH_DYLIB: 0x6, /* dynamicly bound shared library file*/
|
||||
MH_DYLINKER: 0x7, /* dynamic link editor */
|
||||
MH_BUNDLE: 0x8, /* dynamicly bound bundle file */
|
||||
MH_DYLIB_STUB: 0x9,
|
||||
MH_DSYM: 0xa,
|
||||
MH_KEXT_BUNDLE: 0xb,
|
||||
|
||||
DESCRIPTION: function(search) {
|
||||
let result = FILE_TYPES[search];
|
||||
return (result != undefined) ? result : search;
|
||||
},
|
||||
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
},
|
||||
|
||||
debugdescription: ""
|
||||
};
|
||||
|
||||
FILE_TYPES[FILE_TYPE.MH_OBJECT] = 'Relocatable Object File';
|
||||
FILE_TYPES[FILE_TYPE.MH_EXECUTE] = 'Demand Paged Executable File';
|
||||
FILE_TYPES[FILE_TYPE.MH_FVMLIB] = 'Fixed Virtual Memory Shared Library File';
|
||||
FILE_TYPES[FILE_TYPE.MH_CORE] = 'Core File';
|
||||
FILE_TYPES[FILE_TYPE.MH_PRELOAD] = 'Preloaded Executable File';
|
||||
FILE_TYPES[FILE_TYPE.MH_DYLIB] = 'Dynamically Bound Shared Library File';
|
||||
FILE_TYPES[FILE_TYPE.MH_DYLINKER] = 'Dynamic Link Editor';
|
||||
FILE_TYPES[FILE_TYPE.MH_BUNDLE] = 'Dynamically Bound Bundle File';
|
||||
FILE_TYPES[FILE_TYPE.MH_DYLIB_STUB] = 'Dynamic Library Predefined Symbol';
|
||||
FILE_TYPES[FILE_TYPE.MH_DSYM] = 'Dynamic Symbol';
|
||||
FILE_TYPES[FILE_TYPE.MH_KEXT_BUNDLE] = 'Kernel Extension Bundle';
|
||||
|
||||
let FILE_FLAG = {
|
||||
MH_NOUNDEFS: 0x1, /* the object file has no undefined references, can be executed */
|
||||
MH_INCRLINK: 0x2, /* the object file is the output of an incremental link against a base file and can't be link edited again */
|
||||
MH_DYLDLINK: 0x4, /* the object file is input for the dynamic linker and can't be staticly link edited again */
|
||||
MH_BINDATLOAD: 0x8, /* the object file's undefined references are bound by the dynamic linker when loaded. */
|
||||
MH_PREBOUND: 0x10, /* the file has it's dynamic undefined references prebound. */
|
||||
|
||||
DESCRIPTION: function(search) {
|
||||
|
||||
let result = FILE_FLAGS[search];
|
||||
return (result != undefined) ? result : search;
|
||||
},
|
||||
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
FILE_FLAGS[FILE_FLAG.MH_NOUNDEFS] = 'The object file has no undefined references and is executable.';
|
||||
FILE_FLAGS[FILE_FLAG.MH_INCRLINK] = 'The object file is the output of an incremental link against a base file and can not be link edited again.';
|
||||
FILE_FLAGS[FILE_FLAG.MH_DYLDLINK] = 'The object file is the input for the dynamic linker and can not be staticly link edited again.';
|
||||
FILE_FLAGS[FILE_FLAG.MH_BINDATLOAD] = 'The object file\'s undefined references are bound by the dynamic linker when loaded.';
|
||||
FILE_FLAGS[FILE_FLAG.MH_PREBOUND] = 'The file has it\'s dynamic undefined references prebound.';
|
||||
|
||||
|
||||
export { FILE_TYPES, FILE_FLAGS, FILE_TYPE, FILE_FLAG }
|
||||
31
helpers/macho/macho.flags.js
Normal file
31
helpers/macho/macho.flags.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
let FLAGS = {
|
||||
NOUNDEFS: 1,
|
||||
INCRLINK: 2,
|
||||
DYLDLINK: 4,
|
||||
BINDATLOAD: 8,
|
||||
PREBOUND: 16,
|
||||
SPLIT_SEGS: 32,
|
||||
LAZY_INIT: 64,
|
||||
TWOLEVEL: 128,
|
||||
FORCE_FLAT: 256,
|
||||
NOMULTIDEFS: 512,
|
||||
NOFIXPREBINDING: 1024,
|
||||
PREBINDABLE: 2048,
|
||||
ALLMODSBOUND: 4096,
|
||||
SUBSECTIONS_VIA_SYMBOLS: 8192,
|
||||
CANONICAL: 32768,
|
||||
WEAK_DEFINES: 32768,
|
||||
BINDS_TO_WEAK: 65536,
|
||||
ALLOW_STACK_EXECUTION: 131072,
|
||||
ROOT_SAFE: 262144,
|
||||
SETUID_SAFE: 524288,
|
||||
NOREEXPORTED_DYLIBS: 1048576,
|
||||
PIE: 2097152,
|
||||
DEAD_STRIPPABLE_DYLIB: 4194304,
|
||||
HAS_TLV_DESCRIPTORS: 8388608,
|
||||
NO_HEAP_EXECUTION: 16777216,
|
||||
APP_EXTENSION_SAFE: 33554432
|
||||
toString: function(){
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
17
helpers/macho/macho.fvmlib.js
Normal file
17
helpers/macho/macho.fvmlib.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
var Fvmlib = function Fvmlib(name, minor_version, header_addr) {
|
||||
this.name = name || 0x00000000;
|
||||
this.minor_version = minor_version || 0x00000000;
|
||||
this.header_addr = header_addr || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
|
||||
var FvmlibCommand = function FvmlibCommand(cmd, cmdsize, fvmlib) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.fvmlib = fvmlib || new Fvmlib(); //needs better input validation
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
49
helpers/macho/macho.header.js
Normal file
49
helpers/macho/macho.header.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
//Mach-O Fat file header
|
||||
export var FatHeader = function FatHeader() {
|
||||
this.magic = 0x00000000;
|
||||
this.nfat_arch = 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
//Mach-O Fat file header
|
||||
export var FatArch = function FatArch() {
|
||||
this.cputype = 0x00000000;
|
||||
this.cpusubtype = 0x00000000;
|
||||
this.offset = 0x00000000;
|
||||
this.size = 0x00000000;
|
||||
this.align = 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
}
|
||||
|
||||
//Mach-O Binary Executable header 32-bit
|
||||
export var MachoHeader = function MachoHeader() {
|
||||
this.magic = 0x00000000;
|
||||
this.cputype = 0x00000000;
|
||||
this.cpusubtype = 0x00000000;
|
||||
this.filetype = 0x00000000;
|
||||
this.ncmds = 0x00000000;
|
||||
this.sizeofcmds = 0x00000000;
|
||||
this.flags = 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
//Mach-O Binary Executable header 64-bit
|
||||
export var MachoHeader64 = function MachoHeader64() {
|
||||
this.magic = 0x00000000;
|
||||
this.cputype = 0x00000000;
|
||||
this.cpusubtype = 0x00000000;
|
||||
this.filetype = 0x00000000;
|
||||
this.ncmds = 0x00000000;
|
||||
this.sizeofcmds = 0x00000000;
|
||||
this.flags = 0x00000000;
|
||||
this.reserved = 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
256
helpers/macho/macho.js
Normal file
256
helpers/macho/macho.js
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
//macho.js
|
||||
//Written by Sem Voigtländer
|
||||
//Licensed under the MIT License
|
||||
|
||||
import { mime_binary } from './mimetypes.js'
|
||||
import { ReadUint32, ReadUint16LE, ReadUint32LE } from './memory.js'
|
||||
|
||||
import { uint32_t, uint64_t } from './macho.constants.js'
|
||||
import { MAGIC } from './macho.magic.js'
|
||||
import { MachoHeader64 } from './macho.header.js'
|
||||
import { LOAD_COMMAND_TYPE, LoadCommand } from './macho.loadcommand.js'
|
||||
import { CPU_TYPE, CPU_SUB_TYPE } from './macho.cpu.js'
|
||||
import { FILE_FLAGS, FILE_TYPE } from './macho.file.js'
|
||||
|
||||
function default_callback(buffer) {
|
||||
console.log('Received ' + buffer.byteLength / (1024 * 1024) + ' MB');
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/57139182/1397641
|
||||
async function arrayBufferToBlob( buffer ) {
|
||||
return new Blob([buffer])
|
||||
}
|
||||
|
||||
var ChunkReader = function ChunkReader(file, chunksize = (1024 * 1024), callback = default_callback) {
|
||||
|
||||
if(file == undefined) {
|
||||
throw new Error('Invalid argument for file parameter.');
|
||||
}
|
||||
|
||||
if(window.readers == undefined) { window.readers = []; } //Free list
|
||||
this.chunksize = chunksize; //Read a kilobyte at a time
|
||||
this.filesize = file.size;
|
||||
this.offset = 0;
|
||||
|
||||
//Start reading the chunks
|
||||
while(this.offset + this.chunksize <= this.filesize) {
|
||||
|
||||
this.blob = file.slice(this.offset, this.offset+this.chunksize);
|
||||
|
||||
window.readers[window.readers.length] = new FileReader();
|
||||
window.readers[window.readers.length-1].onloadend = function(e) {
|
||||
callback(e.target.result);
|
||||
};
|
||||
window.readers[window.readers.length-1].readAsArrayBuffer(this.blob);
|
||||
console.log('Sending chunk from 0x'+this.offset.toString(16));
|
||||
this.offset+=this.chunksize;
|
||||
}
|
||||
|
||||
for(obj = 0; obj < window.readers.length; obj++) {
|
||||
window.readers[obj] = undefined;
|
||||
}
|
||||
|
||||
free("window.readers");
|
||||
};
|
||||
|
||||
export default function MachoParser(file, callbackElement = document.body) {
|
||||
|
||||
//properties
|
||||
this.reader = new FileReader();
|
||||
|
||||
function writeToCallback(val) {
|
||||
if(callbackElement) {
|
||||
callbackElement.innerHTML +='<tr>'+val+'</tr>';
|
||||
} else {
|
||||
throw new Error('Invalid callback.');
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@Function FindMagic
|
||||
@Params (Uint8Array) buffer, (bool) breakwhenfound
|
||||
@Return (Array) offsets of found magics
|
||||
*/
|
||||
function FindMagic(data, breakwhenfound = false) {
|
||||
var results = [];
|
||||
for(var byte = 0; byte < (data.length - uint32_t); byte++) { //Read 32-bits at a time until the end of the buffer
|
||||
var magic = ReadUint32(data, byte); //Read the next 32-bit magic value
|
||||
if(MAGIC.VALIDATE(magic)) {
|
||||
results.push(byte);
|
||||
if(breakwhenfound) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@Function MapFlags
|
||||
@Params (Uint8Array)flags, (Object)map
|
||||
@Return (Object) key-value mapped dictionary
|
||||
*/
|
||||
function MapFlags(value, map) {
|
||||
var res = {};
|
||||
for (var bit = 1; (value < 0 || bit <= value) && bit !== 0; bit <<= 1)
|
||||
if (value & bit) res[map[bit]] = true; //If value and the bit are equal then map the value to the result
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function ParseCommand(type, data, size, off) {
|
||||
var cmd = null;
|
||||
if(type == LOAD_COMMAND_TYPE.LC_SEGMENT) {
|
||||
if(data.length < 48) {
|
||||
if(window.verbose){console.log('Segment command OOB');}
|
||||
return new LoadCommand(type, data, size, off);
|
||||
}
|
||||
let name = new Cstr(data.slice(0, (4*uint32_t)));
|
||||
cmd = new SegmentCommand(
|
||||
type,
|
||||
size,
|
||||
name,
|
||||
ReadUint32(data, (4*uint32_t)),
|
||||
ReadUint32(data, (5*uint32_t)),
|
||||
ReadUint32(data, (6*uint32_t)),
|
||||
ReadUint32(data, (7*uint32_t)),
|
||||
ReadUint32(data, (8*uint32_t)),
|
||||
ReadUint32(data, (9*uint32_t)),
|
||||
ReadUint32(data, (10*uint32_t)),
|
||||
ReadUint32(data, (11*uint32_t))
|
||||
);
|
||||
|
||||
function prot(p) {
|
||||
var res = {read: false, write: false, exec: false};
|
||||
return res;
|
||||
}
|
||||
|
||||
let sectSize = 17 * uint32_t;
|
||||
var sections = [];
|
||||
//for(var i = 0, off = 48; i < nsects)
|
||||
return cmd;
|
||||
} else {
|
||||
return new LoadCommand(type, data, size, off);
|
||||
}
|
||||
}
|
||||
|
||||
this.reader.onloadend = function(e) {
|
||||
|
||||
let fileType = mime_binary;
|
||||
|
||||
//Handle the file buffer and eventually create a Blob of the result
|
||||
// blobUtil.
|
||||
arrayBufferToBlob(e.target.result, fileType).then(function(blob) {
|
||||
|
||||
let filesize = ((blob.size / 1024) / 1024); //Calculate FileSize in Megabyte
|
||||
window.tempFile = blob;
|
||||
|
||||
//Set up the file and print out for verbosity
|
||||
writeToCallback('<td><strong>File</strong></td><td>'+file.name.toString()+'</td>');
|
||||
writeToCallback('<td><strong>Size</strong></td><td>' + filesize.toFixed(2).toString() + 'MB</td>');
|
||||
|
||||
//Construct a new 8-bit array from the file buffer
|
||||
let data = new Uint8Array(e.target.result);
|
||||
let magics = FindMagic(data, false); //Try to find all Mach-O magics in the byte array
|
||||
|
||||
if(window.debug) { console.log('Parsing all magics...'); }
|
||||
|
||||
//If magics where found, parse the binary.
|
||||
if(magics.length > 0) {
|
||||
|
||||
for(var cMagic = 0; cMagic < magics.length; cMagic++) { //Start parsing the binary from each found magic's offset
|
||||
|
||||
let magicOff = magics[cMagic]; //The offset of the magic currently being parsed
|
||||
let magic = ReadUint32(data, magicOff); //Read the magic from the byte array
|
||||
let littleendian = MAGIC.ISLITTLEENDIAN(magic); //Get the endianness of the magic
|
||||
let x64 = MAGIC.IS64BIT(magic); //Check which bit architecture is being used
|
||||
|
||||
window.machoObj = {}; //Create the Mach-O information object
|
||||
window.machoObj.bits = (x64 ? "64-bit" : "32-bit"); //Get the architecture
|
||||
window.machoObj.endianness = (littleendian ? "little endian" : "big endian"); //Get the endianness
|
||||
window.machoObj.header = (x64 ? new MachoHeader64() : new MachoHeader()); //Depending on architecture, construct a new header
|
||||
window.machoObj.header.magic = magic; //Add the magic to the header
|
||||
window.machoObj.header.cputype = (littleendian ? ReadUint16LE(data, magicOff+uint32_t) : ReadUint16(data, magicOff+uint32_t)); //Read the cputype which comes after the magic
|
||||
window.machoObj.header.cpusubtype = (littleendian ? ReadUint16LE(data, magicOff+(2*uint32_t)) : ReadUint16(data, magicOff+(2*uint32_t))); //Read the cpu subtype which comes after the cputype
|
||||
window.machoObj.header.filetype = (littleendian ? ReadUint32LE(data, magicOff+(3*uint32_t)) : ReadUint32(data, magicOff+(3*uint32_t))); //Read the file type which comes after the cpu subtype
|
||||
window.machoObj.header.ncmds = (littleendian ? ReadUint32LE(data, magicOff+(4*uint32_t)) : ReadUint32(data, magicOff+(4*uint32_t))); //Read the number of commands which comes after the filetype
|
||||
window.machoObj.header.sizeofcmds =(littleendian ? ReadUint32LE(data, magicOff+(5*uint32_t)) : ReadUint32(data, magicOff+(5*uint32_t))); //Read the size of the commands which comes after the number of commands
|
||||
window.machoObj.header.flags = (littleendian ? ReadUint32LE(data, magicOff+(6*uint32_t)) : ReadUint32(data, magicOff+(6*uint32_t))); //Read the flags which come after the size of the commands
|
||||
window.machoObj.loadcommands = [];
|
||||
|
||||
var align = (x64 ? uint64_t : uint32_t); //Depending on our architecture set an align for parsing the load commands
|
||||
|
||||
for(var i = 0, off = magicOff; off < data.length, i < window.machoObj.header.ncmds; i++) {
|
||||
|
||||
var curr_cmd = {};
|
||||
curr_cmd.cmd = (littleendian ? ReadUint32LE(data, off) : ReadUint32(data, off)); //Read the command type from the offset
|
||||
curr_cmd.cmdsize = (littleendian ? ReadUint32LE(data, off+align) : ReadUint32(data, off+align)); //Read the size of the command from the offset
|
||||
curr_cmd.fileoff = off; //Add the offset of the loadcommand for later use
|
||||
curr_cmd.data = data.slice(off, curr_cmd.cmdsize);
|
||||
|
||||
curr_cmd = ParseCommand(curr_cmd.cmd, curr_cmd.data, curr_cmd.cmdsize, curr_cmd.fileoff);
|
||||
if(curr_cmd.cmdsize > 0) { //Commands with a size of zero are not valid or not interesting
|
||||
window.machoObj.loadcommands.push(curr_cmd);
|
||||
}
|
||||
|
||||
off+=8;
|
||||
|
||||
i++; //Increate the loadcommand counter
|
||||
}
|
||||
|
||||
/* Parse all collected information to Human Readable strings */
|
||||
writeToCallback('');
|
||||
writeToCallback('<td><strong>Header</strong></td>');
|
||||
writeToCallback('<td><strong>Offset</strong></td><td>0x'+magicOff.toString(16)+'</td>');
|
||||
writeToCallback('<td><strong>Magic</strong></td><td>0x'+window.machoObj.header.magic.toString(16)+'</td>');
|
||||
writeToCallback('<td><strong>Bits</strong></td><td>'+window.machoObj.bits+'</td>');
|
||||
writeToCallback('<td><strong>Endianness</strong></td><td>'+window.machoObj.endianness+'</td>');
|
||||
writeToCallback('<td><strong>Processor type</strong></td><td>' + CPU_TYPE.DESCRIPTION(window.machoObj.header.cputype)+'</td>');
|
||||
writeToCallback('<td><strong>Processor subtype</strong></td><td>'+ CPU_SUB_TYPE.ARM.DESCRIPTION(window.machoObj.header.cpusubtype)+'</td>');
|
||||
writeToCallback('<td><strong>File type</strong></td><td>'+FILE_TYPE.DESCRIPTION(window.machoObj.header.filetype)+'</td>');
|
||||
writeToCallback('<td><strong>Number of commands</strong></td><td>'+window.machoObj.header.ncmds+'</td>');
|
||||
writeToCallback('<td><strong>Size of commands</strong></td><td>'+window.machoObj.header.sizeofcmds+'</td>');
|
||||
|
||||
window.machoObj.header.flags = MapFlags(window.machoObj.header.flags, FILE_FLAGS);
|
||||
window.machoObj.header.flags = Object.keys(window.machoObj.header.flags).map(function(k) { if(k){return k}});
|
||||
|
||||
writeToCallback('<td><strong>Flags</strong></td><td>'+window.machoObj.header.flags.toString().replace(',','<br>').replace(',','<br>')+"</td>");
|
||||
writeToCallback('');
|
||||
writeToCallback('<td><strong>Load Command</strong></td><td><strong>Size</strong></td><td><strong>Offset</strong></td>');
|
||||
for(var curr_lc = 0; curr_lc < window.machoObj.loadcommands.length; curr_lc++) {
|
||||
writeToCallback(
|
||||
'<td>'+
|
||||
LOAD_COMMAND_TYPE.DESCRIPTION(window.machoObj.loadcommands[curr_lc].cmd) +
|
||||
'</td>'+
|
||||
'<td>'+
|
||||
window.machoObj.loadcommands[curr_lc].cmdsize+
|
||||
'</td>'+
|
||||
'<td>'+
|
||||
' 0x' + window.machoObj.loadcommands[curr_lc].fileoff.toString(16) +
|
||||
'</td>');
|
||||
}
|
||||
magicOff = null;
|
||||
littleendian = null;
|
||||
x64 = null;
|
||||
|
||||
|
||||
// blobUtil.
|
||||
arrayBufferToBlob(data.buffer, fileType).then(function(blob){
|
||||
if(!window.tempFiles) { window.tempFiles = []; }
|
||||
window.tempFiles[window.tempFiles.length] = blob;
|
||||
}).catch(console.log.bind(console));
|
||||
}
|
||||
console.log('The parser has finished');
|
||||
} else { //(magics.length <= 0) (If we end up here it means no magics were found in the file).
|
||||
writeToCallback('This is not a valid Mach-O file.');
|
||||
}
|
||||
|
||||
}).catch(console.log.bind(console));
|
||||
};
|
||||
|
||||
this.reader.readAsArrayBuffer(file);
|
||||
|
||||
console.log('Parsing, please wait...');
|
||||
|
||||
};
|
||||
9
helpers/macho/macho.linkeditdata.js
Normal file
9
helpers/macho/macho.linkeditdata.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
var LinkeditDataCommand = function LinkeditDataCommand(cmd, cmdsize, dataoff, datasize) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.dataoff = dataoff || 0x00000000;
|
||||
this.datasize = datasize || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
133
helpers/macho/macho.loadcommand.js
Normal file
133
helpers/macho/macho.loadcommand.js
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
//Global Constants
|
||||
var LOAD_COMMAND_TYPES = [];
|
||||
|
||||
/*
|
||||
@Class LoadCommand
|
||||
|
||||
@Description
|
||||
*/
|
||||
let LOAD_COMMAND_TYPE = {
|
||||
LC_UNKNOWN: 0,
|
||||
LC_SEGMENT: 1,
|
||||
LC_SYMTAB: 2, //Symbol table
|
||||
LC_SYMSEG: 3, //Segment
|
||||
LC_THREAD: 4,
|
||||
LC_UNIXTHREAD: 5,
|
||||
LC_LOADFVMLIB: 6, /* load a specified fixed VM shared library */
|
||||
LC_IDFVMLIB: 7, /* fixed VM shared library identification */
|
||||
LC_IDENT: 8, /* object identification info (obsolete) */
|
||||
LC_FVMFILE: 9, /* fixed VM file inclusion (internal use) */
|
||||
LC_PREPAGE: 10, /* prepage command (internal use) */
|
||||
LC_DYSYMTAB: 11, /* dynamic link-edit symbol table info */
|
||||
LC_LOAD_DYLIB: 12, /* load a dynamicly linked shared library */
|
||||
LC_ID_DYLIB: 13, /* dynamicly linked shared lib identification */
|
||||
LC_LOAD_DYLINKER: 14, /* load a dynamic linker */
|
||||
LC_ID_DYLINKER: 15,
|
||||
LC_PREBOUND_DYLIB: 16, /* modules prebound for a dynamicly */
|
||||
LC_ROUTINES: 17,
|
||||
LC_SUB_FRAMEWORK: 18,
|
||||
LC_SUB_UMBRELLA: 19,
|
||||
LC_SUB_CLIENT: 20,
|
||||
LC_SUB_LIBRARY: 21,
|
||||
LC_TWOLEVEL_HINTS: 22,
|
||||
LC_PREBIND_CKSUM: 23,
|
||||
LC_SEGMENT_64: 25,
|
||||
LC_ROUTINES_64: 26,
|
||||
LC_UUID: 27,
|
||||
LC_CODE_SIGNATURE: 29,
|
||||
LC_SEGMENT_SPLIT_INFO: 30,
|
||||
LC_LAZY_LOAD_DYLIB: 32,
|
||||
LC_ENCRYPTION_INFO: 33,
|
||||
LC_DYLD_INFO: 34,
|
||||
LC_VERSION_MIN_MACOSX: 36,
|
||||
LC_VERSION_MIN_IPHONEOS: 37,
|
||||
LC_FUNCTION_STARTS: 38,
|
||||
LC_DYLD_ENVIRONMENT: 39,
|
||||
LC_DATA_IN_CODE: 41,
|
||||
LC_SOURCE_VERSION: 42,
|
||||
LC_DYLIB_CODE_SIGN_DRS: 43,
|
||||
LC_ENCRYPTION_INFO_64: 44,
|
||||
LC_LINKER_OPTION: 45,
|
||||
LC_LINKER_OPTIMIZATION_HINT: 46,
|
||||
LC_VERSION_MIN_TVOS: 47,
|
||||
LC_VERSION_MIN_WATCHOS: 48,
|
||||
LC_NOTE: 49,
|
||||
LC_BUILD_VERSION: 50,
|
||||
LC_LOAD_WEAK_DYLIB: 2147483672,
|
||||
LC_RPATH: 2147483676,
|
||||
LC_REEXPORT_DYLIB: 2147483679,
|
||||
LC_DYLD_INFO_ONLY: 2147483682,
|
||||
LC_LOAD_UPWARD_DYLIB: 2147483683,
|
||||
LC_MAIN: 2147483688,
|
||||
|
||||
DESCRIPTION: function(search) {
|
||||
let result = LOAD_COMMAND_TYPES[search];
|
||||
return (result != undefined) ? result : search;
|
||||
},
|
||||
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_SEGMENT] = '32-bits Segment command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_SYMTAB] = 'Symbol table command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_SYMSEG] = 'Symbol segment command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_THREAD] = 'Thread command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_UNIXTHREAD] = 'UNIX Thread command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_LOADFVMLIB] = 'Fixed Virtual Memory Library Load command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_IDFVMLIB] = 'Fixed Virtual Memory Library identification information command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_IDENT] = 'Object identification information command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_FVMFILE] = 'Fixed VM File inclusion commmand';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_PREPAGE] = 'Prepage command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_DYSYMTAB] = 'Dynamic Link-Edit Symbol Table information command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_LOAD_DYLIB] = 'Dynamically linked shared library identification command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_ID_DYLIB] = 'Dynamic Library Identifier';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_LOAD_DYLINKER] = 'Dynamic Linker Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_ID_DYLINKER] = 'Dynamic Linker Identifier';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_PREBOUND_DYLIB] = 'Prebound Dynamic Library Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_ROUTINES] = 'Routines Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_SUB_FRAMEWORK] = 'Sub Framework Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_SUB_UMBRELLA] = 'Sub Umbrella Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_SUB_CLIENT] = 'Sub Client Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_SUB_LIBRARY] = 'Sub Library Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_TWOLEVEL_HINTS] = 'TwoLevel Hints Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_PREBIND_CKSUM] = 'Prebind Checksum Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_SEGMENT_64] = '64-bits Segment Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_ROUTINES_64] = '64-bits Routines Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_UUID] = 'UUID Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_CODE_SIGNATURE] = 'Code Signature';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_SEGMENT_SPLIT_INFO] = 'Segment Split Information Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_LAZY_LOAD_DYLIB] = 'Lazy Dynamic Library Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_ENCRYPTION_INFO] = '32-bits encryption Information';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_DYLD_INFO] = 'Dynamic Loader Information Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_VERSION_MIN_MACOSX] = 'Minimum Version Requirement Command for OSX';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_VERSION_MIN_IPHONEOS] = 'Minimum Version Requirement Command for iPhone';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_FUNCTION_STARTS] = 'Function Starts Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_DYLD_ENVIRONMENT] = 'Dynamic Loader Environment Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_DATA_IN_CODE] = 'Data In Code Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_SOURCE_VERSION] = 'Source Version Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_DYLIB_CODE_SIGN_DRS] = 'Dynamic Library Code Sign Directories Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_ENCRYPTION_INFO_64] = '64-bits Encryption Information';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_LINKER_OPTION] = 'Linker Option Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_LINKER_OPTIMIZATION_HINT] = 'Linker Optimization Hint';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_VERSION_MIN_TVOS] = 'Minimum Version Requirement Command for tvOS';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_VERSION_MIN_WATCHOS] = 'Minimum Version Requirement Command for watchOS';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_NOTE] = 'Additional Note';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_BUILD_VERSION] = 'Build Version';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_LOAD_WEAK_DYLIB] = 'Weak Dynamic Library Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_RPATH] = 'Executable Path';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_REEXPORT_DYLIB] = 'Re-Exported Dynamic Library Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_DYLD_INFO_ONLY] = 'Dynamic Library Loader Information Only';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_LOAD_UPWARD_DYLIB] = 'Upward Dynamic Library Load Command';
|
||||
LOAD_COMMAND_TYPES[LOAD_COMMAND_TYPE.LC_MAIN] = 'Main Entrypoint';
|
||||
|
||||
var LoadCommand = function LoadCommand(type, data, size, fileoff) {
|
||||
this.cmd = type || 0;
|
||||
this.cmdsize = size || 0;
|
||||
this.data = data || new Uint8Array();
|
||||
this.fileoff = fileoff || 0;
|
||||
};
|
||||
|
||||
|
||||
export { LOAD_COMMAND_TYPE, LOAD_COMMAND_TYPES, LoadCommand }
|
||||
72
helpers/macho/macho.magic.js
Normal file
72
helpers/macho/macho.magic.js
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
//Global Constants
|
||||
var MAGICS = [];
|
||||
|
||||
|
||||
/*
|
||||
@Class MAGIC
|
||||
|
||||
@Description
|
||||
Magic is a specific byte that indicates what for file it is.
|
||||
In Mach-O there a multiple magics differing from endianess, bits or file type.
|
||||
*/
|
||||
let MAGIC =
|
||||
{
|
||||
|
||||
//Macho Magics
|
||||
FAT_MAGIC: 0xcafebabe,
|
||||
FAT_CIGAM: 0xbebafeca,
|
||||
FAT_MAGIC64: 0xcafebabf,
|
||||
FAT_CIGAM64: 0xbfbafeca,
|
||||
MH_MAGIC: 0xfeedface,
|
||||
MH_CIGAM: 0xcefaedfe,
|
||||
MH_MAGIC64: 0xfeedfacf,
|
||||
MH_CIGAM64: 0xcffaedfe,
|
||||
|
||||
//Retrieve the magic name of a specified magic
|
||||
//If an invalid magic was specifed undefined is returned
|
||||
KEYFORVALUE: function(value) {
|
||||
return MAGICS[value];
|
||||
},
|
||||
|
||||
//Validate that a specified magic is correct
|
||||
VALIDATE: function(magic) {
|
||||
|
||||
return MAGIC.KEYFORVALUE(magic) != undefined;
|
||||
},
|
||||
|
||||
//returns true if the specified magic is a little-endian magic
|
||||
ISLITTLEENDIAN: function(magic) {
|
||||
|
||||
if(!MAGIC.VALIDATE(magic)) //If it is not a valid magic we are basically done here
|
||||
return false;
|
||||
|
||||
return MAGIC.KEYFORVALUE(magic).split('CIGAM').length > 1; //hacky trick to check if the magic value's keyname contains CIGAM which basically indicates little endian
|
||||
},
|
||||
|
||||
//returns true if the specified magic is 64-bit
|
||||
IS64BIT: function(magic) {
|
||||
|
||||
if(!MAGIC.VALIDATE(magic))
|
||||
return false;
|
||||
|
||||
return MAGIC.KEYFORVALUE(magic).split('64').length > 1; //hacky trick to check if the magic value's keyname contains 64 which basically indicates 64-bit
|
||||
},
|
||||
|
||||
toString : function() {
|
||||
return JSON.stringify(this);
|
||||
},
|
||||
|
||||
debugdescription: ""
|
||||
};
|
||||
|
||||
MAGICS[MAGIC.FAT_MAGIC] = "FAT_MAGIC";
|
||||
MAGICS[MAGIC.FAT_CIGAM] = "FAT_CIGAM";
|
||||
MAGICS[MAGIC.FAT_MAGIC64] = "FAT_MAGIC64";
|
||||
MAGICS[MAGIC.FAT_CIGAM64] = "FAT_CIGAM64";
|
||||
MAGICS[MAGIC.MH_MAGIC] = "MH_MAGIC";
|
||||
MAGICS[MAGIC.MH_CIGAM] = "MH_CIGAM";
|
||||
MAGICS[MAGIC.MH_MAGIC64] = "MH_MAGIC64";
|
||||
MAGICS[MAGIC.MH_CIGAM64] = "MH_CIGAM64";
|
||||
|
||||
|
||||
export { MAGIC, MAGICS }
|
||||
25
helpers/macho/macho.operators.js
Normal file
25
helpers/macho/macho.operators.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
let OPERATORS = {
|
||||
False: 0,
|
||||
True: 1,
|
||||
Ident: 2,
|
||||
AppleAnchor: 3,
|
||||
AnchorHash: 4,
|
||||
InfoKeyValue: 5,
|
||||
And: 6,
|
||||
Or: 7,
|
||||
CDHash: 8,
|
||||
Not: 9,
|
||||
InfoKeyField: 10,
|
||||
CertField: 11,
|
||||
TrustedCert: 12,
|
||||
TrustedCerts: 13,
|
||||
CertGeneric: 14,
|
||||
AppleGenericAnchor: 15,
|
||||
EntitlementField: 16,
|
||||
CertPolicy: 17,
|
||||
NamedAnchor: 18,
|
||||
Platform: 20,
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
8
helpers/macho/macho.prebindcksum.js
Normal file
8
helpers/macho/macho.prebindcksum.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
var PrebindCksumCommand = function PrebindCksumCommand(cmd, cmdsize, cksum) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.cksum = cksum || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
10
helpers/macho/macho.prebounddylib.js
Normal file
10
helpers/macho/macho.prebounddylib.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
var PreboundDylibCommand = function PreboundDylibCommand(cmd, cmdsize, name, nmodules, linked_modules) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.name = name || 0x00000000;
|
||||
this.nmodules = nmodules || 0x00000000;
|
||||
this.linked_modules = linked_modules || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
30
helpers/macho/macho.routines.js
Normal file
30
helpers/macho/macho.routines.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
var RoutinesCommand = function RoutinesCommand(cmd, cmdsize, init_address, init_module, reserved1, reserved2, reserved3, reserved4, reserved5, reserved6) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.init_address = init_address || 0x00000000;
|
||||
this.init_module = init_module || 0x00000000;
|
||||
this.reserved1 = reserved1 || 0x00000000;
|
||||
this.reserved2 = reserved2 || 0x00000000;
|
||||
this.reserved3 = reserved3 || 0x00000000;
|
||||
this.reserved4 = reserved4 || 0x00000000;
|
||||
this.reserved5 = reserved5 || 0x00000000;
|
||||
this.reserved6 = reserved6 || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
var RoutinesCommand64 = function RoutinesCommand64(cmd, cmdsize, init_address, init_module, reserved1, reserved2, reserved3, reserved4, reserved5, reserved6) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.init_address = init_address || 0x0000000000000000;
|
||||
this.init_module = init_module || 0x0000000000000000;
|
||||
this.reserved1 = reserved1 || 0x0000000000000000;
|
||||
this.reserved2 = reserved2 || 0x0000000000000000;
|
||||
this.reserved3 = reserved3 || 0x0000000000000000;
|
||||
this.reserved4 = reserved4 || 0x0000000000000000;
|
||||
this.reserved5 = reserved5 || 0x0000000000000000;
|
||||
this.reserved6 = reserved6 || 0x0000000000000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
8
helpers/macho/macho.rpath.js
Normal file
8
helpers/macho/macho.rpath.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
var RpathCommand = function RpathCommand(cmd, cmdsize, path) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.path = path || 0x00000000;
|
||||
this.toString = function() {
|
||||
JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
90
helpers/macho/macho.section.js
Normal file
90
helpers/macho/macho.section.js
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
//Global Constants
|
||||
|
||||
let SECTION_MASK = {
|
||||
SECTION_TYPE: 0x000000ff,
|
||||
SECTION_ATTRIBUTES: 0xffffff00
|
||||
toString = function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
let SECTION_TYPE = {
|
||||
REGULAR: 0,
|
||||
ZEROFILL: 1,
|
||||
CSTRING_LITERALS: 2,
|
||||
BYTE4_LITERALS: 3,
|
||||
BYTE8_LITERALS: 4,
|
||||
LITERAL_POINTERS: 5,
|
||||
NON_LAZY_SYMBOL_POINTERS: 6,
|
||||
LAZY_SYMBOL_POINTERS: 7,
|
||||
SYMBOL_STUBS: 8,
|
||||
MOD_INIT_FUNC_POINTERS: 9,
|
||||
MOD_TERM_FUNC_POINTERS: 0xa,
|
||||
COALESCED: 0xb,
|
||||
GB_ZEROFILL: 0xc,
|
||||
INTERPOSING: 0xd,
|
||||
BYTE16_LITERALS: 0xe,
|
||||
DTRACE_DOF: 0xf,
|
||||
LAZY_DYLIB_SYMBOL_POINTERS: 0x10,
|
||||
THREAD_LOCAL_REGULAR: 0x11,
|
||||
THREAD_LOCAL_ZEROFILL: 0x12,
|
||||
THREAD_LOCAL_VARIABLES: 0x13,
|
||||
THREAD_LOCAL_VARIABLE_POINTERS: 0x14,
|
||||
THREAD_LOCAL_INIT_FUNCTION_POINTERS: 0x15,
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
let SECTION = {
|
||||
SECT_TEXT: "__text",
|
||||
SECT_FVMLIB_INIT0: "__fvmlib_init0",
|
||||
SECT_FVMLIB_INIT1: "__fvmlib_init1",
|
||||
SECT_DATA: "__data",
|
||||
SECT_BSS: "__bss",
|
||||
SECT_COMMON: "__common",
|
||||
SECT_OBJC_SYMBOLS: "__symbol_table",
|
||||
SECT_OBJC_MODULES: "__module_info",
|
||||
SECT_OBJC_STRINGS: "__selector_strs",
|
||||
SECT_OBJC_REFS: "__selector_refs",
|
||||
SECT_ICON_HEADER: "__header",
|
||||
SECT_ICON_TIFF: "__tiff",
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
var Section = function Section(sectname, segname, addr, size, offset, align, reloff, nreloc, flags, reserved1, reserved2) {
|
||||
this.sectname = new Uint8Array(16);
|
||||
this.segname = new Uint8Array(16);
|
||||
this.addr = addr || 0x00000000;
|
||||
this.size = size || 0x00000000;
|
||||
this.offset = offset || 0x00000000;
|
||||
this.align = align || 0x00000000;
|
||||
this.reloff = reloff || 0x00000000;
|
||||
this.nreloc = nreloc || 0x00000000;
|
||||
this.flags = flags || 0x00000000;
|
||||
this.reserved1 = reserved1 || 0x00000000;
|
||||
this.reserved2 = reserved2 || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
|
||||
var Section64 = function Section64(sectname, segname, addr, size, offset, align, reloff, nreloc, flags, reserved1, reserved2, reserved3) {
|
||||
this.sectname = new Uint8Array(16);
|
||||
this.segname = new Uint8Array(16);
|
||||
this.addr = addr || 0x0000000000000000;
|
||||
this.size = size || 0x0000000000000000;
|
||||
this.offset = offset || 0x00000000;
|
||||
this.align = align || 0x00000000;
|
||||
this.reloff = reloff || 0x00000000;
|
||||
this.nreloc = nreloc || 0x00000000;
|
||||
this.flags = flags || 0x00000000;
|
||||
this.reserved1 = reserved1 || 0x00000000;
|
||||
this.reserved2 = reserved2 || 0x00000000;
|
||||
this.reserved3 = reserved3 || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
70
helpers/macho/macho.segment.js
Normal file
70
helpers/macho/macho.segment.js
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
//Global Constants
|
||||
var SG_FLAGS = [];
|
||||
|
||||
let SG_FLAG = {
|
||||
SG_HIGHVM: 0x1,
|
||||
SG_FVMLIB: 0x2,
|
||||
SG_NORELOC: 0x4,
|
||||
|
||||
DESCRIPTION: function(search) {
|
||||
let result = SG_FLAGS[search];
|
||||
return (result != undefined) ? result : search;
|
||||
},
|
||||
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
SG_FLAGS[SG_FLAG.SG_HIGHVM] = 'SG_HIGHVM';
|
||||
SG_FLAGS[SG_FLAG.SG_FVMLIB] = 'SG_FVMLIB';
|
||||
SG_FLAGS[SG_FLAG.SG_NORELOC] = 'SG_NORELOC';
|
||||
|
||||
let SEGMENT = {
|
||||
SEG_PAGEZERO: "__PAGEZERO",
|
||||
SEG_TEXT: "__TEXT",
|
||||
SEG_ICON: "__ICON",
|
||||
SEG_OBJC: "__OBJC",
|
||||
SEG_LINKEDIT: "__LINKEDIT",
|
||||
SEG_UNIXSTACK: "__UNIXSTACK",
|
||||
SEG_DATA: "__DATA",
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
|
||||
//32-bits segment command
|
||||
var SegmentCommand = function SegmentCommand(type, size, segname, vmaddr, vmsize, fileoff, filesize, maxprot, initprot, nsects, flags) {
|
||||
this.cmd = type || 0x00000000;
|
||||
this.cmdsize = size || 0x00000000;
|
||||
this.segname = new TextEncoder("utf-8").encode(segname) || new Uint8Array(16);
|
||||
this.vmaddr = vmaddr || 0x00000000;
|
||||
this.vmsize = vmsize || 0x00000000;
|
||||
this.fileoff = fileoff || 0x00000000;
|
||||
this.filesize = filesize || 0x00000000;
|
||||
this.maxprot = maxprot || 0x00000000;
|
||||
this.initprot = initprot || 0x00000000;
|
||||
this.nsects = nsects || 0x00000000;
|
||||
this.flags = flags || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
|
||||
//64-bits segment command
|
||||
var SegmentCommand64 = function SegmentCommand64(cmd, cmdsize, segname, vmaddr, vmsize, fileoff, filesize, maxprot, initprot, nsects, flags) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.segname = new TextEncoder("utf-8").encode(segname) || new Uint8Array(16);
|
||||
this.vmaddr = vmaddr || 0x0000000000000000;
|
||||
this.vmsize = vmsize || 0x0000000000000000;
|
||||
this.fileoff = fileoff || 0x0000000000000000;
|
||||
this.filesize = filesize || 0x0000000000000000;
|
||||
this.maxprot = maxprot || 0x00000000;
|
||||
this.initprot = initprot || 0x00000000;
|
||||
this.nsects = nsects || 0x00000000;
|
||||
this.flags = flags || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
12
helpers/macho/macho.signatures.js
Normal file
12
helpers/macho/macho.signatures.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
//Global Constants
|
||||
|
||||
let SIGNATURES = {
|
||||
REQUIREMENT: 0xfade0c00,
|
||||
REQUIREMENTS: 0xfade0c01,
|
||||
CODEDIRECTORY: 0xfade0c02,
|
||||
ENTITLEMENT: 0xfade7171,
|
||||
BLOBWRAPPER: 0xfade0b01,
|
||||
EMBEDDED_SIGNATURE: 0xfade0cc0,
|
||||
DETACHED_SIGNATURE: 0xfade0cc1,
|
||||
CODE_SIGN_DRS: 0xfade0c05
|
||||
};
|
||||
40
helpers/macho/macho.stabs.js
Normal file
40
helpers/macho/macho.stabs.js
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
let STABS = {
|
||||
GSYM: 0x20,
|
||||
FNAME: 0x22,
|
||||
FUN: 0x24,
|
||||
STSYM: 0x26,
|
||||
LCSYM: 0x28,
|
||||
MAIN: 0x2a,
|
||||
BNSYM: 0x2e,
|
||||
PC: 0x30,
|
||||
AST: 0x32,
|
||||
MAC_UNDEF: 0x3a,
|
||||
OPT: 0x3c,
|
||||
RSYM: 0x40,
|
||||
SLINE: 0x44,
|
||||
DSLINE: 0x46,
|
||||
BSLINE: 0x48,
|
||||
ENSYM: 0x4e,
|
||||
SSYM: 0x60,
|
||||
SO: 0x64,
|
||||
OSO: 0x66,
|
||||
LSYM: 0x80,
|
||||
BINCL: 0x82,
|
||||
SOL: 0x84,
|
||||
PARAMS: 0x86,
|
||||
VERSION: 0x88,
|
||||
OLEVEL: 0x8a,
|
||||
PSYM: 0xa0,
|
||||
EINCL: 0xa2,
|
||||
ENTRY: 0xa4,
|
||||
LBRAC: 0xc0,
|
||||
EXCL: 0xc2,
|
||||
RBRAC: 0xe0,
|
||||
BCOMM: 0xe2,
|
||||
ECOMM: 0xe4,
|
||||
ECOML: 0xe8,
|
||||
LENG: 0xfe,
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
8
helpers/macho/macho.subclient.js
Normal file
8
helpers/macho/macho.subclient.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
var SubClientCommand = function SubClientCommand(cmd, cmdsize, client) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.client = client || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
5
helpers/macho/macho.subframework.js
Normal file
5
helpers/macho/macho.subframework.js
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
var SubFrameworkCommand = function SubFrameworkCommand(cmd, cmdsize, umbrella) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.umbrella = umbrella || 0x00000000;
|
||||
};
|
||||
8
helpers/macho/macho.sublibrary.js
Normal file
8
helpers/macho/macho.sublibrary.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
var SubLibraryCommand = function SubLibraryCommand(cmd, cmdsize, sub_library) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.sub_library = sub_library || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
8
helpers/macho/macho.subumbrella.js
Normal file
8
helpers/macho/macho.subumbrella.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
var SubUmbrellaCommand = function SubUmbrellaCommand(cmd, cmdsize, sub_umbrella) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.sub_umbrella = sub_umbrella || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
56
helpers/macho/macho.symtab.js
Normal file
56
helpers/macho/macho.symtab.js
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
var SymtabCommand = function SymtabCommand(cmd, cmdsize, symoff, nsyms, stroff, strsize) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.symoff = symoff || 0x00000000;
|
||||
this.nsyms = nsyms || 0x00000000;
|
||||
this.stroff = stroff || 0x00000000;
|
||||
this.strsize = strsize || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
|
||||
var DySymtabCommand = function DySymtabCommand(cmd,
|
||||
cmdsize,
|
||||
ilocalsym,
|
||||
nlocalsym,
|
||||
iextdefsym,
|
||||
nextdefsym,
|
||||
iundefsym,
|
||||
nundefsym,
|
||||
ntoc,
|
||||
modtaboff,
|
||||
nmodtab,
|
||||
extrefsymoff,
|
||||
nextrefsymoff,
|
||||
nextrefsyms,
|
||||
indirectsymoff,
|
||||
ninderectsyms,
|
||||
extreloff,
|
||||
nextrel,
|
||||
locreloff,
|
||||
nlocrel) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.ilocalsym = ilocalsym || 0x00000000;
|
||||
this.nlocalsym = nlocalsym || 0x00000000;
|
||||
this.iextdefsym = iextdefsym || 0x00000000;
|
||||
this.nextdefsym = nextdefsym || 0x00000000;
|
||||
this.iundefsym = iundefsym || 0x00000000;
|
||||
this.nundefsym = nundefsym || 0x00000000;
|
||||
this.ntoc = ntoc || 0x00000000;
|
||||
this.modtaboff = modtaboff || 0x00000000;
|
||||
this.nmodtab = nmodtab || 0x00000000;
|
||||
this.extrefsymoff = extrefsymoff || 0x00000000;
|
||||
this.nextrefsymoff = nextrefsymoff || 0x00000000;
|
||||
this.nextrefsyms = nextrefsyms || 0x00000000;
|
||||
this.indirectsymoff= indirectsymoff || 0x00000000;
|
||||
this.ninderectsyms = ninderectsyms || 0x00000000;
|
||||
this.extreloff = extreloff || 0x00000000;
|
||||
this.nextrel = nextrel || 0x00000000;
|
||||
this.locreloff = locreloff || 0x00000000;
|
||||
this.nlocrel = nlocrel || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
8
helpers/macho/macho.thread.js
Normal file
8
helpers/macho/macho.thread.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
var ThreadCommand = function ThreadCommand(cmd, cmdsize, name) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.name = name || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
17
helpers/macho/macho.twolevelhints.js
Normal file
17
helpers/macho/macho.twolevelhints.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
var TwoLevelHintsCommand = function TwoLevelHintsCommand(cmd, cmdsize, offset, nhints) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.offset = offset || 0x00000000;
|
||||
this.nhints = nhints || 0x00000000;
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
|
||||
var TwoLevelHint = {
|
||||
isub_image:8,
|
||||
itoc:24,
|
||||
toString: function() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
};
|
||||
8
helpers/macho/macho.uuid.js
Normal file
8
helpers/macho/macho.uuid.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
var UUIDCommand = function UUIDCommand(cmd, cmdsize, uuid) {
|
||||
this.cmd = cmd || 0x00000000;
|
||||
this.cmdsize = cmdsize || 0x00000000;
|
||||
this.uuid = uuid || new Uint8Array(16); //needs better input validation
|
||||
this.toString = function() {
|
||||
return JSON.stringify(this);
|
||||
};
|
||||
};
|
||||
429
helpers/macho/memory.js
Normal file
429
helpers/macho/memory.js
Normal file
|
|
@ -0,0 +1,429 @@
|
|||
//memory.js
|
||||
//Written by Sem Voigtländer
|
||||
//Licensed under the MIT License
|
||||
|
||||
/*
|
||||
Functionality for geting the memory size of a javascript object
|
||||
*/
|
||||
|
||||
export function free(objectName)
|
||||
{
|
||||
if(eval(objectName) != 'undefined')
|
||||
{
|
||||
console.log('Helping the garbage collector a little bit with freeing.');
|
||||
eval(objectName + '=undefined;');
|
||||
}
|
||||
}
|
||||
|
||||
export function sizeof(object) {
|
||||
|
||||
var objectList = [];
|
||||
var stack = [object];
|
||||
var bytes = 0;
|
||||
|
||||
while (stack.length) {
|
||||
var value = stack.pop();
|
||||
|
||||
if (typeof value === 'boolean') {
|
||||
bytes += 4;
|
||||
} else if (typeof value === 'string') {
|
||||
bytes += value.length * 2;
|
||||
} else if (typeof value === 'number') {
|
||||
bytes += 8;
|
||||
} else if (
|
||||
typeof value === 'object' &&
|
||||
objectList.indexOf(value) === -1
|
||||
) {
|
||||
objectList.push(value);
|
||||
|
||||
for (var i in value) {
|
||||
stack.push(value[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
Functions for swapping the endianness of an integer
|
||||
Supports 16, 32 and 64 bit integers. (Experimental 128-bits as well)
|
||||
Smaller integers are automatically casted to the corresponding size.
|
||||
Bigger integers are not casted to smaller integers as they may lose precision.
|
||||
*/
|
||||
|
||||
export function SwapEndian16(integer) {
|
||||
|
||||
var _hex = '0';
|
||||
var _output = '';
|
||||
|
||||
//Input validation
|
||||
if(typeof integer !== 'number')
|
||||
throw new Error('Invalid argument. argument provided is not an integer.');
|
||||
if(integer < 0)
|
||||
throw new Error('Invalid argument. argument provided may not be negative.');
|
||||
|
||||
_hex = integer.toString(16); //Conver the input to a hexadecimal string
|
||||
|
||||
//Conver the hexadecimal string to a 16-bit integer hexadecimal string
|
||||
while(_hex.length < 4)
|
||||
_hex = '0'+_hex;
|
||||
|
||||
let _arr = _hex.split(''); //Convert the 16-bit integer hexadecimal string to a char array
|
||||
|
||||
//Sanity check
|
||||
if (_arr.length != 4)
|
||||
throw new Error('Invalid argument. argument provided is not a 16-bit integer.');
|
||||
|
||||
|
||||
//Swap the endianness
|
||||
_output += (_arr[2] + _arr[3]).toString();
|
||||
_output += (_arr[0] + _arr[1]).toString();
|
||||
|
||||
//Output sanity check
|
||||
if(_output.length != 4)
|
||||
throw new Error('Sanity check failed. Output is not a 16-bit integer');
|
||||
|
||||
_output = parseInt('0x'+_output); //convert the hexadecimal output string to an integer
|
||||
|
||||
//Conversion sanity check
|
||||
if(_output === NaN)
|
||||
throw new Error('Conversion from a hexadecimal string to an integer failed.');
|
||||
|
||||
return _output;
|
||||
}
|
||||
|
||||
export function SwapEndian32(integer) {
|
||||
|
||||
var _hex = '0';
|
||||
var _output = '';
|
||||
|
||||
//Input validation
|
||||
if(typeof integer !== 'number')
|
||||
throw new Error('Invalid argument. argument provided is not an integer.');
|
||||
if(integer < 0)
|
||||
throw new Error('Invalid argument. argument provided may not be negative.');
|
||||
|
||||
_hex = integer.toString(16); //Conver the input to a hexadecimal string
|
||||
|
||||
//Conver the hexadecimal string to a 32-bit integer hexadecimal string
|
||||
while(_hex.length < 8)
|
||||
_hex = '0'+_hex;
|
||||
|
||||
let _arr = _hex.split(''); //Convert the 32-bit integer hexadecimal string to a char array
|
||||
|
||||
//Sanity check
|
||||
if (_arr.length != 8)
|
||||
throw new Error('Invalid argument. argument provided is not a 32-bit integer.');
|
||||
|
||||
|
||||
//Swap the endianness
|
||||
_output += (_arr[6] + _arr[7]).toString();
|
||||
_output += (_arr[4] + _arr[5]).toString();
|
||||
_output += (_arr[2] + _arr[3]).toString();
|
||||
_output += (_arr[0] + _arr[1]).toString();
|
||||
|
||||
//Output sanity check
|
||||
if(_output.length != 8)
|
||||
throw new Error('Sanity check failed. Output is not a 32-bit integer');
|
||||
|
||||
_output = parseInt('0x'+_output); //convert the hexadecimal output string to an integer
|
||||
|
||||
//Conversion sanity check
|
||||
if(_output === NaN)
|
||||
throw new Error('Conversion from a hexadecimal string to an integer failed.');
|
||||
|
||||
//Lets help javascripts garbage collector a bit
|
||||
_arr = undefined;
|
||||
_hex = undefined;
|
||||
|
||||
return _output;
|
||||
}
|
||||
|
||||
export function SwapEndian64(integer) {
|
||||
|
||||
var _hex = '0';
|
||||
var _output = '';
|
||||
|
||||
//Input validation
|
||||
if(typeof integer !== 'number')
|
||||
throw new Error('Invalid argument. argument provided is not an integer.');
|
||||
if(integer < 0)
|
||||
throw new Error('Invalid argument. argument provided may not be negative.');
|
||||
|
||||
_hex = integer.toString(16); //Conver the input to a hexadecimal string
|
||||
|
||||
//Conver the hexadecimal string to a 64-bit integer hexadecimal string
|
||||
while(_hex.length < 16)
|
||||
_hex = '0'+_hex;
|
||||
|
||||
let _arr = _hex.split(''); //Convert the 64-bit integer hexadecimal string to a char array
|
||||
|
||||
//Sanity check
|
||||
if (_arr.length != 16)
|
||||
throw new Error('Invalid argument. argument provided is not a 64-bit integer.');
|
||||
|
||||
|
||||
//Swap the endianness
|
||||
_output += (_arr[14] + _arr[15]).toString();
|
||||
_output += (_arr[12] + _arr[13]).toString();
|
||||
_output += (_arr[10] + _arr[11]).toString();
|
||||
_output += (_arr[8] + _arr[9]).toString();
|
||||
_output += (_arr[6] + _arr[7]).toString();
|
||||
_output += (_arr[4] + _arr[5]).toString();
|
||||
_output += (_arr[2] + _arr[3]).toString();
|
||||
_output += (_arr[0] + _arr[1]).toString();
|
||||
|
||||
//Output sanity check
|
||||
if(_output.length != 16)
|
||||
throw new Error('Sanity check failed. Output is not a 64-bit integer');
|
||||
|
||||
_output = parseInt('0x'+_output); //convert the hexadecimal output string to an integer
|
||||
|
||||
//Conversion sanity check
|
||||
if(_output === NaN)
|
||||
throw new Error('Conversion from a hexadecimal string to an integer failed.');
|
||||
|
||||
//Lets help javascripts garbage collector a bit
|
||||
_arr = undefined;
|
||||
_hex = undefined;
|
||||
|
||||
return _output;
|
||||
}
|
||||
|
||||
export function SwapEndian128(integer) {
|
||||
|
||||
var _hex = '0';
|
||||
var _output = '';
|
||||
|
||||
//Input validation
|
||||
if(typeof integer !== 'number')
|
||||
throw new Error('Invalid argument. argument provided is not an integer.');
|
||||
if(integer < 0)
|
||||
throw new Error('Invalid argument. argument provided may not be negative.');
|
||||
|
||||
_hex = integer.toString(16); //Conver the input to a hexadecimal string
|
||||
|
||||
//Conver the hexadecimal string to a 128-bit integer hexadecimal string
|
||||
while(_hex.length < 32)
|
||||
_hex = '0'+_hex;
|
||||
|
||||
let _arr = _hex.split(''); //Convert the 128-bit integer hexadecimal string to a char array
|
||||
|
||||
//Sanity check
|
||||
if (_arr.length != 32)
|
||||
throw new Error('Invalid argument. argument provided is not a 128-bit integer.');
|
||||
|
||||
|
||||
//Swap the endianness
|
||||
_output += (_arr[30] + _arr[31]).toString();
|
||||
_output += (_arr[28] + _arr[29]).toString();
|
||||
_output += (_arr[26] + _arr[27]).toString();
|
||||
_output += (_arr[24] + _arr[25]).toString();
|
||||
_output += (_arr[22] + _arr[23]).toString();
|
||||
_output += (_arr[20] + _arr[21]).toString();
|
||||
_output += (_arr[18] + _arr[19]).toString();
|
||||
_output += (_arr[16] + _arr[17]).toString();
|
||||
_output += (_arr[14] + _arr[15]).toString();
|
||||
_output += (_arr[12] + _arr[13]).toString();
|
||||
_output += (_arr[10] + _arr[11]).toString();
|
||||
_output += (_arr[8] + _arr[9]).toString();
|
||||
_output += (_arr[6] + _arr[7]).toString();
|
||||
_output += (_arr[4] + _arr[5]).toString();
|
||||
_output += (_arr[2] + _arr[3]).toString();
|
||||
_output += (_arr[0] + _arr[1]).toString();
|
||||
|
||||
//Output sanity check
|
||||
if(_output.length != 32)
|
||||
throw new Error('Sanity check failed. Output is not a 128-bit integer');
|
||||
|
||||
_output = parseInt('0x'+_output); //convert the hexadecimal output string to an integer
|
||||
|
||||
//Conversion sanity check
|
||||
if(_output === NaN)
|
||||
throw new Error('Conversion from a hexadecimal string to an integer failed.');
|
||||
|
||||
//Lets help javascripts garbage collector a bit
|
||||
_arr = undefined;
|
||||
_hex = undefined;
|
||||
|
||||
return _output;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Functions for reading integers from a given offset in a given array.
|
||||
Supports 16, 32 and 64 bit integers. (Experimental 128-bits as well)
|
||||
It also supports reading with a different Endianness.
|
||||
|
||||
*/
|
||||
|
||||
//Big Endian
|
||||
export function ReadUint16(arr, off) {
|
||||
|
||||
if(arr.length < 2 || off > arr.length) //sanity check
|
||||
throw new Error('Cannot read OOB.');
|
||||
|
||||
return parseInt("0x" +
|
||||
arr[off].toString(16) +
|
||||
arr[off + 1].toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
export function ReadUint32(arr, off) {
|
||||
|
||||
if(arr.length < 4 || off > arr.length) //sanity check
|
||||
throw new Error('Cannot read OOB.');
|
||||
|
||||
return parseInt("0x" +
|
||||
arr[off].toString(16) +
|
||||
arr[off + 1].toString(16) +
|
||||
arr[off + 2].toString(16) +
|
||||
arr[off + 3].toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
export function ReadUint64(arr, off) {
|
||||
|
||||
if(arr.length < 8 || off > arr.length) //sanity check
|
||||
throw new Error('Cannot read OOB.');
|
||||
|
||||
return parseInt("0x" +
|
||||
arr[off].toString(16) +
|
||||
arr[off + 1].toString(16) +
|
||||
arr[off + 2].toString(16) +
|
||||
arr[off + 3].toString(16) +
|
||||
arr[off + 4].toString(16) +
|
||||
arr[off + 5].toString(16) +
|
||||
arr[off + 6].toString(16) +
|
||||
arr[off + 7].toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
export function ReadUint128(arr, off) {
|
||||
|
||||
if(arr.length < 16 || off > arr.length) //sanity check
|
||||
throw new Error('Cannot read OOB.');
|
||||
|
||||
return parseInt("0x" +
|
||||
arr[off].toString(16) +
|
||||
arr[off + 1].toString(16) +
|
||||
arr[off + 2].toString(16) +
|
||||
arr[off + 3].toString(16) +
|
||||
arr[off + 4].toString(16) +
|
||||
arr[off + 5].toString(16) +
|
||||
arr[off + 6].toString(16) +
|
||||
arr[off + 7].toString(16) +
|
||||
arr[off + 8].toString(16) +
|
||||
arr[off + 9].toString(16) +
|
||||
arr[off + 10].toString(16) +
|
||||
arr[off + 11].toString(16) +
|
||||
arr[off + 12].toString(16) +
|
||||
arr[off + 13].toString(16) +
|
||||
arr[off + 14].toString(16) +
|
||||
arr[off + 15].toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
//Little Endian
|
||||
export function ReadUint16LE(arr, off) {
|
||||
|
||||
if(arr.length < 2 || off > arr.length) //sanity check
|
||||
throw new Error('Cannot read OOB.');
|
||||
|
||||
return parseInt("0x" +
|
||||
arr[off + 1].toString(16) +
|
||||
arr[off].toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
export function ReadUint32LE(arr, off) {
|
||||
if(arr.length < 4 || off > arr.length) //sanity check
|
||||
throw new Error('Cannot read OOB.');
|
||||
|
||||
return parseInt("0x" +
|
||||
arr[off + 3].toString(16) +
|
||||
arr[off + 2].toString(16) +
|
||||
arr[off + 1].toString(16) +
|
||||
arr[off].toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
export function ReadUint64LE(arr, off) {
|
||||
|
||||
if(arr.length < 8 || off > arr.length) //sanity check
|
||||
throw new Error('Cannot read OOB.');
|
||||
|
||||
return parseInt("0x" +
|
||||
arr[off + 7].toString(16) +
|
||||
arr[off + 6].toString(16) +
|
||||
arr[off + 5].toString(16) +
|
||||
arr[off + 4].toString(16) +
|
||||
arr[off + 3].toString(16) +
|
||||
arr[off + 2].toString(16) +
|
||||
arr[off + 1].toString(16) +
|
||||
arr[off].toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
export function ReadUint128LE(arr, off) {
|
||||
|
||||
if(arr.length < 16 || off > arr.length) //sanity check
|
||||
throw new Error('Cannot read OOB.');
|
||||
|
||||
return parseInt("0x" +
|
||||
arr[off + 15].toString(16) +
|
||||
arr[off + 14].toString(16) +
|
||||
arr[off + 13].toString(16) +
|
||||
arr[off + 12].toString(16) +
|
||||
arr[off + 11].toString(16) +
|
||||
arr[off + 10].toString(16) +
|
||||
arr[off + 9].toString(16) +
|
||||
arr[off + 8].toString(16) +
|
||||
arr[off + 7].toString(16) +
|
||||
arr[off + 6].toString(16) +
|
||||
arr[off + 5].toString(16) +
|
||||
arr[off + 4].toString(16) +
|
||||
arr[off + 3].toString(16) +
|
||||
arr[off + 2].toString(16) +
|
||||
arr[off + 1].toString(16) +
|
||||
arr[off].toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
export function writeUint8(arr, off, val) {
|
||||
if(arr.length < 2 || off > arr.length || off < 0) {
|
||||
throw new Error('Cannot write OOB.');
|
||||
}
|
||||
|
||||
|
||||
if(val.length > 0xff)
|
||||
throw new Error('Invalid argument. This should be a valid 8-bit integer.');
|
||||
let old = arr[off];
|
||||
arr[off] = val;
|
||||
}
|
||||
|
||||
export function writeUint16(arr, off, val) {
|
||||
if(arr.length < 4 || off > arr.length || off < 0) { //We should never underflow or overflow our buffer
|
||||
throw new Error('Cannot write OOB.');
|
||||
}
|
||||
|
||||
|
||||
if(val.length > 0xffff) //Values that after serialization never will be a 16 bit integer should never be treated
|
||||
throw new Error('Invalid argument. This should be a valid 16-bit integer.');
|
||||
|
||||
let old = new Array(arr[off], arr[off+1]);
|
||||
|
||||
if(val <= 0xff) { //Integers below 256 are always valid
|
||||
arr[off] = val;
|
||||
|
||||
} else if(val > 0xff && val <= 0xfff) { //Integers bigger than 256 but below 4096 should be treated as two bytes instead of one and fixed with a leading zero
|
||||
arr[off] = parseInt('0x'+(val.toString(16).split('')[0] + val.toString(16).split('')[1]));
|
||||
arr[off+1] = parseInt('0x0'+val.toString(16).split('')[2]);
|
||||
|
||||
} else if(val > 0xff && val <= 0xffff) { //Integers bigger than 256 and below 65535 should be treated as two bytes and can be splitted without having to fix them with a leading zero
|
||||
arr[off] = parseInt('0x'+(val.toString(16).split('')[0] + val.toString(16).split('')[1]));
|
||||
arr[off+1] = parseInt('0x'+val.toString(16).split('')[2] + val.toString(16).split('')[3]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
6
helpers/macho/mimetypes.js
Normal file
6
helpers/macho/mimetypes.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
//MimeTypes Library
|
||||
|
||||
export let mime_binary = 'application/octet-stream';
|
||||
export let mime_zip = 'application/octet-stream';
|
||||
export let mime_html = 'text/html';
|
||||
export let mime_text = 'text/plain';
|
||||
Loading…
Add table
Add a link
Reference in a new issue