Ejemplo n.º 1
0
int main()
{
// NSObjectFileImage APIs are only available on Mac OS X - not iPhone OS
#if __MAC_OS_X_VERSION_MIN_REQUIRED
	int fd = open("test.bundle", O_RDONLY, 0);
	if ( fd == -1 ) {
		FAIL("open() failed");
		return 1;
	}

	struct stat stat_buf;
	if ( fstat(fd, &stat_buf) == -1) {
		FAIL("fstat() failed");
		return 0;
	}

	void* loadAddress = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
	if ( loadAddress == ((void*)(-1)) ) {
		FAIL("mmap() failed");
		return 0;
	}

	close(fd);

	NSObjectFileImage ofi;
	if ( NSCreateObjectFileImageFromMemory(loadAddress, stat_buf.st_size, &ofi) != NSObjectFileImageSuccess ) {
		FAIL("NSCreateObjectFileImageFromMemory failed");
		return 0;
	}
	
	NSModule mod = NSLinkModule(ofi, "he_he", NSLINKMODULE_OPTION_NONE);
	if ( mod == NULL ) {
		FAIL("NSLinkModule failed");
		return 0;
	}
	
	// look for he_he string in list of images loaded
	struct dyld_all_image_infos* infos = getImageInfosFromKernel();

	if ( infos->infoArrayCount < 2 ) {
		FAIL("bundle-memory-load-all-images: dyld_all_image_infos.infoArrayCount is  < 2");
		return 0;
	}

	bool found = false;
	for( int i=0; i < infos->infoArrayCount; ++i) {
		//fprintf(stderr, "infos->infoArray[%d].imageLoadAddress=%p %s\n", i, infos->infoArray[i].imageLoadAddress, infos->infoArray[i].imageFilePath);
		if ( infos->infoArray[i].imageFilePath == NULL ) {
			FAIL("bundle-memory-load-all-images: NULL image path found");
			exit(0);
		}
		if ( strcmp(infos->infoArray[i].imageFilePath, "he_he") == 0 )
			found = true;
	}
	
	if ( !found ) {
		FAIL("bundle-memory-load-all-images: loaded memory bundle 'he_he' nout found");
		return 0;
	}

	if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
		FAIL("NSUnLinkModule failed");
		return 0;
	}

	if ( !NSDestroyObjectFileImage(ofi) ) {
		FAIL("NSDestroyObjectFileImage failed");
		return 0;
	}
	
	// Should check that loadAddress is unmmaped now (by call to NSDestroyObjectFileImage)
#endif

	PASS("bundle-memory-load-all-images");
	return 0;
}
Ejemplo n.º 2
0
static void checkBundle(const char* path, bool unlinkBeforeDestroy)
{
	int fd = open(path, O_RDONLY, 0);
	if ( fd == -1 ) {
		printf("[FAIL] open(%s) failed", path);
		exit(0);
	}

	struct stat stat_buf;
	if ( fstat(fd, &stat_buf) == -1) {
		printf("[FAIL] fstat() failed\n");
		exit(0);
	}

	void* loadAddress = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
	if ( loadAddress == ((void*)(-1)) ) {
		printf("[FAIL] mmap() failed\n");
		exit(0);
	}

	close(fd);

	NSObjectFileImage ofi;
	if ( NSCreateObjectFileImageFromMemory(loadAddress, stat_buf.st_size, &ofi) != NSObjectFileImageSuccess ) {
		printf("[FAIL] NSCreateObjectFileImageFromMemory failed\n");
		exit(0);
	}

	NSModule mod = NSLinkModule(ofi, path, NSLINKMODULE_OPTION_NONE);
	if ( mod == NULL ) {
		printf("[FAIL] NSLinkModule failed\n");
		exit(0);
	}
	
   if ( !unlinkBeforeDestroy ) {
        // API lets you destroy ofi and NSModule lives on
        if ( !NSDestroyObjectFileImage(ofi) ) {
            printf("[FAIL] NSDestroyObjectFileImage failed\n");
            exit(0);
        }
    }

	NSSymbol sym = NSLookupSymbolInModule(mod, "_fooInBundle");
	if ( sym == NULL ) {
		printf("[FAIL] NSLookupSymbolInModule failed\n");
		exit(0);
	}

	void* func = NSAddressOfSymbol(sym);
	if ( func == NULL ) {
		printf("[FAIL] NSAddressOfSymbol failed\n");
		exit(0);
	}

    Dl_info info;
    if ( dladdr(func, &info) == 0 ) {
        printf("[FAIL] dladdr(&p, xx) failed\n");
        exit(0);
    }
    //printf("_fooInBundle found in %s\n", info.dli_fname);

    if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
            printf("[FAIL] NSUnLinkModule failed\n");
            exit(0);
    }

    if ( dladdr(func, &info) != 0 ) {
        printf("[FAIL] dladdr(&p, xx) found but should not have\n");
        exit(0);
    }

    if ( unlinkBeforeDestroy ) {
        if ( !NSDestroyObjectFileImage(ofi) ) {
            printf("[FAIL] NSDestroyObjectFileImage failed\n");
            exit(0);
        }
    }
}
Ejemplo n.º 3
0
MODULE_SCOPE int
TclpLoadMemory(
    Tcl_Interp *interp,		/* Used for error reporting. */
    void *buffer,		/* Buffer containing the desired code
				 * (allocated with TclpLoadMemoryGetBuffer). */
    int size,			/* Allocation size of buffer. */
    int codeSize,		/* Size of code data read into buffer or -1 if
				 * an error occurred and the buffer should
				 * just be freed. */
    Tcl_LoadHandle *loadHandle, /* Filled with token for dynamically loaded
				 * file which will be passed back to
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr)
				/* Filled with address of Tcl_FSUnloadFileProc
				 * function which should be used for this
				 * file. */
{
    Tcl_DyldLoadHandle *dyldLoadHandle;
    NSObjectFileImage dyldObjFileImage = NULL;
    Tcl_DyldModuleHandle *modulePtr;
    NSModule module;
    const char *objFileImageErrMsg = NULL;

    /*
     * Try to create an object file image that we can load from.
     */

    if (codeSize >= 0) {
	NSObjectFileImageReturnCode err = NSObjectFileImageSuccess;
	const struct fat_header *fh = buffer;
	uint32_t ms = 0;
#ifndef __LP64__
	const struct mach_header *mh = NULL;
	#define mh_size  sizeof(struct mach_header)
	#define mh_magic MH_MAGIC
	#define arch_abi 0
#else
	const struct mach_header_64 *mh = NULL;
	#define mh_size  sizeof(struct mach_header_64)
	#define mh_magic MH_MAGIC_64
	#define arch_abi CPU_ARCH_ABI64
#endif

	if ((size_t) codeSize >= sizeof(struct fat_header)
		&& fh->magic == OSSwapHostToBigInt32(FAT_MAGIC)) {
	    uint32_t fh_nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);

	    /*
	     * Fat binary, try to find mach_header for our architecture
	     */

	    TclLoadDbgMsg("Fat binary, %d archs", fh_nfat_arch);
	    if ((size_t) codeSize >= sizeof(struct fat_header) +
		    fh_nfat_arch * sizeof(struct fat_arch)) {
		void *fatarchs = (char*)buffer + sizeof(struct fat_header);
		const NXArchInfo *arch = NXGetLocalArchInfo();
		struct fat_arch *fa;

		if (fh->magic != FAT_MAGIC) {
		    swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
		}
		fa = NXFindBestFatArch(arch->cputype | arch_abi,
			arch->cpusubtype, fatarchs, fh_nfat_arch);
		if (fa) {
		    TclLoadDbgMsg("NXFindBestFatArch() successful: "
			    "local cputype %d subtype %d, "
			    "fat cputype %d subtype %d",
			    arch->cputype | arch_abi, arch->cpusubtype,
			    fa->cputype, fa->cpusubtype);
		    mh = (void*)((char*)buffer + fa->offset);
		    ms = fa->size;
		} else {
		    TclLoadDbgMsg("NXFindBestFatArch() failed");
		    err = NSObjectFileImageInappropriateFile;
		}
		if (fh->magic != FAT_MAGIC) {
		    swap_fat_arch(fatarchs, fh_nfat_arch, arch->byteorder);
		}
	    } else {
		TclLoadDbgMsg("Fat binary header failure");
		err = NSObjectFileImageInappropriateFile;
	    }
	} else {
	    /*
	     * Thin binary
	     */

	    TclLoadDbgMsg("Thin binary");
	    mh = buffer;
	    ms = codeSize;
	}
	if (ms && !(ms >= mh_size && mh->magic == mh_magic &&
		 mh->filetype == MH_BUNDLE)) {
	    TclLoadDbgMsg("Inappropriate file: magic %x filetype %d",
		    mh->magic, mh->filetype);
	    err = NSObjectFileImageInappropriateFile;
	}
	if (err == NSObjectFileImageSuccess) {
	    err = NSCreateObjectFileImageFromMemory(buffer, codeSize,
		    &dyldObjFileImage);
	    if (err == NSObjectFileImageSuccess) {
		TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() "
			"successful");
	    } else {
		objFileImageErrMsg = DyldOFIErrorMsg(err);
		TclLoadDbgMsg("NSCreateObjectFileImageFromMemory() failed: %s",
			objFileImageErrMsg);
	    }
	} else {
	    objFileImageErrMsg = DyldOFIErrorMsg(err);
	}
    }

    /*
     * If it went wrong (or we were asked to just deallocate), get rid of the
     * memory block and create an error message.
     */

    if (dyldObjFileImage == NULL) {
	vm_deallocate(mach_task_self(), (vm_address_t) buffer, size);
	if (objFileImageErrMsg != NULL) {
	    Tcl_AppendResult(interp, "NSCreateObjectFileImageFromMemory() "
		    "error: ", objFileImageErrMsg, NULL);
	}
	return TCL_ERROR;
    }

    /*
     * Extract the module we want from the image of the object file.
     */

    module = NSLinkModule(dyldObjFileImage, "[Memory Based Bundle]",
	    NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR);
    NSDestroyObjectFileImage(dyldObjFileImage);
    if (module) {
	TclLoadDbgMsg("NSLinkModule() successful");
    } else {
	NSLinkEditErrors editError;
	int errorNumber;
	const char *errorName, *errMsg;

	NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
	TclLoadDbgMsg("NSLinkModule() failed: %s", errMsg);
	Tcl_AppendResult(interp, errMsg, NULL);
	return TCL_ERROR;
    }

    /*
     * Stash the module reference within the load handle we create and return.
     */

    modulePtr = (Tcl_DyldModuleHandle *) ckalloc(sizeof(Tcl_DyldModuleHandle));
    modulePtr->module = module;
    modulePtr->nextPtr = NULL;
    dyldLoadHandle = (Tcl_DyldLoadHandle *)
	    ckalloc(sizeof(Tcl_DyldLoadHandle));
#if TCL_DYLD_USE_DLFCN
    dyldLoadHandle->dlHandle = NULL;
#endif
    dyldLoadHandle->dyldLibHeader = NULL;
    dyldLoadHandle->modulePtr = modulePtr;
    *loadHandle = (Tcl_LoadHandle) dyldLoadHandle;
    *unloadProcPtr = &TclpUnloadFile;
    return TCL_OK;
}
Ejemplo n.º 4
0
__attribute__ ((constructor)) init(void)
{
    /* load the target file into our buffer */
    int fd = -1;
    if ((fd = open(TARGET, O_RDONLY)) == -1)
    {
        ERROR_MSG("Can't open target %s.", TARGET);
        return;
    }
    struct stat stat = {0};
    if (fstat(fd, &stat) < 0)
    {
        ERROR_MSG("Can't fstat target %s.", TARGET);
        close(fd);
        return;
    }
    
    void *target_buf = NULL;
    kern_return_t kr = 0;
    /* allocate memory with mach_vm_allocate (requisite) and copy the file into it */
    kr = mach_vm_allocate(mach_task_self(), (mach_vm_address_t*)&target_buf, stat.st_size, VM_FLAGS_ANYWHERE);
    if (kr != KERN_SUCCESS)
    {
        ERROR_MSG("Can't allocate buffer for target.");
        close(fd);
        return;
    }
    ssize_t bytes_read = 0;
    bytes_read = pread(fd, target_buf, stat.st_size, 0);
    
    if (bytes_read == -1 ||
        bytes_read < stat.st_size)
    {
        ERROR_MSG("Failed to read target.");
        close(fd);
        return;
    }
    
    /* modify file type to MH_BUNDLE if necessary */
    /* the file type must be MH_BUNDLE but we can convert it on the fly */
    struct mach_header *mh = (struct mach_header*)target_buf;
    if (mh->magic != MH_MAGIC_64)
    {
        ERROR_MSG("Invalid Mach-O target.");
        close(fd);
        return;
    }
    if (mh->filetype != MH_BUNDLE)
    {
        mh->filetype = MH_BUNDLE;
    }
    
    /* now we are ready to call the dyld NS* stuff and get our binary executed */
    NSObjectFileImageReturnCode dyld_err;
    NSObjectFileImage ofi;
    
    dyld_err = NSCreateObjectFileImageFromMemory(target_buf, stat.st_size, &ofi);
    if (dyld_err != NSObjectFileImageSuccess)
    {
        ERROR_MSG("Failed to create object file with error %d", dyld_err);
    }
    const char *moduleName;
    uint32_t options = NSLINKMODULE_OPTION_BINDNOW;
    NSModule m = NULL;
    /* a name for the module so it can be identified by the image observer */
    moduleName = INJECTED_MODULE_NAME;
    /* finally link the module */
    m = NSLinkModule(ofi, moduleName, options);
    if (m == NULL)
    {
        ERROR_MSG("Failed to link module!");
    }
    else
    {
        /* register a dyld image observer
         * we need it because we don't know where the injected image was loaded at
         * it's not our allocated buffer but a new copy of it
         * so we can find that image via the name and execute it from there
         */
        _dyld_register_func_for_add_image(image_observer);
    }
    
    close(fd);

//    /* we can deallocate memory because NSLinkModule will create its own copy */
//    target_buf = NULL;
//    mach_vm_deallocate(mach_task_self(), (mach_vm_address_t)target_buf, stat.st_size);
}