Ejemplo n.º 1
0
void MACHFile::entryPointLoad()
{
    //    nEntryPointOffset=getAddressOfEntryPoint();

    //    _loadEntryPoint();

    if(isMACH64())
    {
        nEntryPointOffset=RVAToOffset64(getEntryPoint());
    }
    else
    {
        nEntryPointOffset=RVAToOffset32(getEntryPoint());
    }

    _loadEntryPoint();
}
Ejemplo n.º 2
0
int entrypoint() {
        struct DIS_fixed disasm_data;
        uint32_t ep = getEntryPoint();
        uint32_t remaining_size = getFilesize() - ep;
        uint32_t current_offset = DisassembleAt(&disasm_data, ep, remaining_size);


        return 0;
}
Ejemplo n.º 3
0
void*
kma_malloc(kma_size_t size)
{
	if (debug) printf("\nREQUEST %i\n", size);
	if (entryPoint == 0) {
		entryPoint = getEntryPoint();
	}
	
	int adjustedSize = size + sizeof(buffer);
	int bufferSize = getBufferSize(adjustedSize);
	freeListInfo* freeList = getFreeList(bufferSize);
	
	if (freeList == NULL) {
		return NULL;
	}
	
	getSpaceIfNeeded(freeList, bufferSize);
	return getNextBuffer(freeList);
}
int entrypoint() {
    // Get the offset of the EP
    uint32_t ep = getEntryPoint(), cur;
    
    // Disassemble one instruction at EP
    struct DIS_fixed instr;
    cur = DisassembleAt(&instr, ep, *__clambc_filesize - ep);
    if(cur == ep) // Failed to disasm
	return 0;

    // Check if it's "mov ebx, value"
    if(instr.x86_opcode != OP_MOV || // Not a MOV
       instr.arg[0].access_type != ACCESS_REG || // Left arg is not a register
       instr.arg[0].u.reg != REG_EBX || // Left arg is not EBX
       instr.arg[1].access_type != ACCESS_IMM // Right arg is not an immediate value
       ) {
	return 0;
    }

    // Take the argument of mov ebx, ... which is the VA of the cyphertext
    uint32_t va_of_cyphertext = instr.arg[1].u.other;
    debug("VA of cyphertext is ");debug(va_of_cyphertext);

    // Make the VA an RVA - that is subtract the imagebase from it
    uint32_t rva_of_cyphertext = va_of_cyphertext -  __clambc_pedata.opt32.ImageBase;
    debug("RVA of cyphertext is ");debug(rva_of_cyphertext);

    // Turn the RVA of the cyphertext into a file (raw) offset
    uint32_t offset_of_cyphertext = pe_rawaddr(rva_of_cyphertext);

    // If the offset is bad, bail out
    if(offset_of_cyphertext == PE_INVALID_RVA) {
	debug("Can't locate the phisical offset of the cyphertext");
	return 0;
    }
    debug("Cyphertext starts at ");debug(offset_of_cyphertext);

    // Move to the cyphertext in the file
    seek(offset_of_cyphertext, SEEK_SET);

    // Make room for the cyphertext to be read - 10 bytes that is "HELLO WORM" plus one byte for the terminator
    uint8_t cyphertext[11];

    // Read the cyphertext from file into "cyphertext"
    if(read(cyphertext, 10)!=10) {
	debug("Can't read 10 bytes of cyphertext\n");
	return 0;
    }

    // The "decryption" loop - turns the cyphertext into playintext
    uint8_t current_position, key = 0x29;
    for(current_position=0; current_position<10; current_position++) {
	key++;
	cyphertext[current_position] ^= key;
	key = cyphertext[current_position];
    }

    // Compare the (now) plaintext with the reference ("HELLO WORM")
    if(!memcmp(cyphertext, "HELLO WORM", 10)) {
	cyphertext[10] = 0; // Add a string terminator
	debug((char *)cyphertext); // Print it, just for fun
	foundVirus("ClamAV-Test-File-detected-via-bytecode"); // Set the virus name!
    }
    return 0;
}
bool PluginPackage::fetchInfo()
{
    PLUGIN_LOG("Fetch Info Loading \"%s\"\n", m_path.utf8().data());

    // Open the library
    void *handle = dlopen(m_path.utf8().data(), RTLD_NOW);
    if(!handle) {
        PLUGIN_LOG("Couldn't load plugin library \"%s\": %s\n",
                   m_path.utf8().data(), dlerror());
        return false;
    }
    PLUGIN_LOG("Fetch Info Loaded %p\n", handle);
    
    // This object will call dlclose() and set m_module to NULL
    // when going out of scope.
    DynamicLibraryCloser dlCloser(&handle);
    
    // Get the three entry points we need for Linux Netscape Plug-ins
    NP_GetMIMEDescriptionFuncPtr NP_GetMIMEDescription;
    NPP_GetValueProcPtr NP_GetValue;
    if(!getEntryPoint(handle, "NP_GetMIMEDescription",
            (void **) &NP_GetMIMEDescription) ||
            !getEntryPoint(handle, "NP_GetValue", (void **) &NP_GetValue)) {
        // If any of those failed to resolve, fail the entire load
        return false;
    }
     
    // Get the plugin name and description using NP_GetValue
    const char *name;
    const char *description;
    if(NP_GetValue(NULL, NPPVpluginNameString, &name) != NPERR_NO_ERROR ||
            NP_GetValue(NULL, NPPVpluginDescriptionString, &description) !=
                NPERR_NO_ERROR) {
        PLUGIN_LOG("Couldn't get name/description using NP_GetValue\n");
        return false;
    }

    PLUGIN_LOG("Plugin name: \"%s\"\n", name);
    PLUGIN_LOG("Plugin description: \"%s\"\n", description);
    m_name = name;
    m_description = description;

    // fileName is just the trailing part of the path
    int last_slash = m_path.reverseFind('/');
    if(last_slash < 0)
        m_fileName = m_path;
    else
        m_fileName = m_path.substring(last_slash + 1);

    // Grab the MIME description. This is in the format, e.g:
    // application/x-somescriptformat:ssf:Some Script Format
    String mimeDescription(NP_GetMIMEDescription());
    PLUGIN_LOG("MIME description: \"%s\"\n", mimeDescription.utf8().data());
    // Clear out the current mappings.
    m_mimeToDescriptions.clear();
    m_mimeToExtensions.clear();    
    // Split the description into its component entries, separated by
    // semicolons.
    Vector<String> mimeEntries;
    mimeDescription.split(';', true, mimeEntries);
    // Iterate through the entries, adding them to the MIME mappings.
    for(Vector<String>::const_iterator it = mimeEntries.begin();
            it != mimeEntries.end(); ++it) {
        // Each part is split into 3 fields separated by colons
        // Field 1 is the MIME type (e.g "application/x-shockwave-flash").
        // Field 2 is a comma separated list of file extensions.
        // Field 3 is a human readable short description.
        const String &mimeEntry = *it;
        Vector<String> fields;
        mimeEntry.split(':', true, fields);
        if(fields.size() != 3) {
            PLUGIN_LOG("Bad MIME entry \"%s\"\n", mimeEntry.utf8().data());
            return false;
        }

        const String& mimeType = fields[0];
        Vector<String> extensions;
        fields[1].split(',', true, extensions);
        const String& description = fields[2];

        determineQuirks(mimeType);

        PLUGIN_LOG("mime_type: \"%s\"\n", mimeType.utf8().data());
        PLUGIN_LOG("extensions: \"%s\"\n", fields[1].utf8().data());
        PLUGIN_LOG("description: \"%s\"\n", description.utf8().data());
         
        // Map the mime type to the vector of extensions and the description
        if(!extensions.isEmpty())
            m_mimeToExtensions.set(mimeType, extensions);
        if(!description.isEmpty())
            m_mimeToDescriptions.set(mimeType, description);
    }

    PLUGIN_LOG("Fetch Info Loaded plugin details ok \"%s\"\n",
            m_path.utf8().data());

    // If this plugin needs to be kept in memory, unload the module now
    // and load it permanently.
    if (m_quirks.contains(PluginQuirkDontUnloadPlugin)) {
        dlCloser.ok();
        dlclose(handle);
        load();
    }
    
    // dlCloser will unload the plugin if required.
    return true;
}
bool PluginPackage::load()
{
    PLUGIN_LOG("tid:%d isActive:%d isLoaded:%d loadCount:%d\n",
               gettid(),
               m_freeLibraryTimer.isActive(),
               m_isLoaded,
               m_loadCount);
    if (m_freeLibraryTimer.isActive()) {
        ASSERT(m_module);
        m_freeLibraryTimer.stop();
    } else if (m_isLoaded) {
        if (m_quirks.contains(PluginQuirkDontAllowMultipleInstances))
            return false;
        m_loadCount++;
        PLUGIN_LOG("Already loaded, count now %d\n", m_loadCount);
        return true;
    }
    ASSERT(m_loadCount == 0);
    ASSERT(m_module == NULL);

    PLUGIN_LOG("Loading \"%s\"\n", m_path.utf8().data());

    // Open the library
    void *handle = dlopen(m_path.utf8().data(), RTLD_NOW);
    if(!handle) {
        PLUGIN_LOG("Couldn't load plugin library \"%s\": %s\n",
                   m_path.utf8().data(), dlerror());
        return false;
    }
    m_module = handle;
    PLUGIN_LOG("Fetch Info Loaded %p\n", m_module);
    // This object will call dlclose() and set m_module to NULL
    // when going out of scope.
    DynamicLibraryCloser dlCloser(&m_module);
    
    
    NP_InitializeFuncPtr NP_Initialize;
    if(!getEntryPoint(m_module, "NP_Initialize", (void **) &NP_Initialize) || 
            !getEntryPoint(handle, "NP_Shutdown", (void **) &m_NPP_Shutdown)) {
        PLUGIN_LOG("Couldn't find Initialize function\n");
        return false;
    }

    // Provide the plugin with our browser function table and grab its
    // plugin table. Provide the Java environment and the Plugin which
    // can be used to override the defaults if the plugin wants.
    initializeBrowserFuncs();
    // call this afterwards, which may re-initialize some methods, but ensures
    // that any additional (or changed) procs are set. There is no real attempt
    // to have this step be minimal (i.e. only what we add/override), since the
    // core version (initializeBrowserFuncs) can change in the future.
    initializeExtraBrowserFuncs(&m_browserFuncs);

    memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs));
    m_pluginFuncs.size = sizeof(m_pluginFuncs);
    if(NP_Initialize(&m_browserFuncs,
                     &m_pluginFuncs,
                     JSC::Bindings::getJNIEnv()) != NPERR_NO_ERROR) {
        PLUGIN_LOG("Couldn't initialize plugin\n");
        return false;
    }

    // Don't close the library - loaded OK.
    dlCloser.ok();
    // Retain the handle so we can close it in the future.
    m_module = handle;
    m_isLoaded = true;
    ++m_loadCount;
    PLUGIN_LOG("Initial load ok, count now %d\n", m_loadCount);
    return true;
}
bool ApplicationDescription::hasRemoteEntryPoint() const
{
    return getEntryPoint().scheme() == "http" ||
           getEntryPoint().scheme() == "https";
}
void GlyphPositionAdjustments::applyCursiveAdjustments(LEGlyphStorage &glyphStorage, le_bool rightToLeft, const LEFontInstance *fontInstance)
{
    if (! hasCursiveGlyphs()) {
        return;
    }

    le_int32 start = 0, end = fGlyphCount, dir = 1;
    le_int32 firstExitPoint = -1, lastExitPoint = -1;
    LEPoint entryAnchor, exitAnchor, pixels;
    LEGlyphID lastExitGlyphID = 0;
    float baselineAdjustment = 0;

    // This removes a possible warning about
    // using exitAnchor before it's been initialized.
    exitAnchor.fX = exitAnchor.fY = 0;

    if (rightToLeft) {
        start = fGlyphCount - 1;
        end = -1;
        dir = -1;
    }

    for (le_int32 i = start; i != end; i += dir) {
        LEGlyphID glyphID = glyphStorage[i];

        if (isCursiveGlyph(i)) {
            if (lastExitPoint >= 0 && getEntryPoint(i, entryAnchor) != NULL) {
                float anchorDiffX = exitAnchor.fX - entryAnchor.fX;
                float anchorDiffY = exitAnchor.fY - entryAnchor.fY;

                baselineAdjustment += anchorDiffY;
                adjustYPlacement(i, baselineAdjustment);

                if (rightToLeft) {
                    LEPoint secondAdvance;

                    fontInstance->getGlyphAdvance(glyphID, pixels);
                    fontInstance->pixelsToUnits(pixels, secondAdvance);

                    adjustXAdvance(i, -(anchorDiffX + secondAdvance.fX));
                } else {
                    LEPoint firstAdvance;

                    fontInstance->getGlyphAdvance(lastExitGlyphID, pixels);
                    fontInstance->pixelsToUnits(pixels, firstAdvance);

                    adjustXAdvance(lastExitPoint, anchorDiffX - firstAdvance.fX);
                }
            }

            lastExitPoint = i;

            if (getExitPoint(i, exitAnchor) != NULL) {
                if (firstExitPoint < 0) {
                    firstExitPoint = i;
                }

                lastExitGlyphID = glyphID;
            } else {
                if (baselineIsLogicalEnd(i) && firstExitPoint >= 0 && lastExitPoint >= 0) {
                    le_int32 limit = lastExitPoint /*+ dir*/;
                    LEPoint dummyAnchor;

                    if (getEntryPoint(i, dummyAnchor) != NULL) {
                        limit += dir;
                    }

                    for (le_int32 j = firstExitPoint; j != limit; j += dir) {
                        if (isCursiveGlyph(j)) {
                            adjustYPlacement(j, -baselineAdjustment);
                        }
                    }
                }

                firstExitPoint = lastExitPoint = -1;
                baselineAdjustment = 0;
            }
        }
    }
}
Ejemplo n.º 9
0
unsigned long long MACHFile::getEntryPointOffset()
{
    return RVAToOffset(getEntryPoint());
}
Ejemplo n.º 10
0
/*
 * addEntry: Adds an entry to a fcb.
 *
 * @start:      Integer Pointer     location of the starting block
 * @fcBlockID:  Integer             the target fcb id
 * @name:       String              name of the entry
 * @type:       Integer             type of the entry
 *
 * return  0:                       successful execution
 * return -1:                       file already exists in directory
 * return -2:                       error retrieving the parent file control block
 * return -3:                       error looking for a free block
 * return -4:                       error finding entry in the file control block
 * return -5:                       error creating file control block
 */
int addEntry(int* start, int fcBlockID, char* name, int type) {
    /* best case:
     *      block: [1, a, b, c, d, e, f, ... ]
     * average case:
     *      block: [1, a, b, c, 0, 0, 0, ... ]
     * worst case:
     *      block: [1, 0, 0, 0, 0, 0, 0, ... ]
     *
     * Therefore, 7 chars must be skipped before any useful data is reached.
     */

    if (getStart(malloc(1), fcBlockID, name) != -2) {
        fprintf(stderr, "File already exists in directory.\n");
        return -1;
    }

    char* fcb = malloc(BLOCK_SIZE);

    if (get_block(fcBlockID, fcb)) {
        fprintf(stderr, "Error retrieving the parent file control block.\n");
        return -2;
    }

    if (getFreeBlock(start)) {
        fprintf(stderr, "Error looking for a free block.\n");
        return -3;
    }

    // Position in the file control block
    int position;

    if (getEntryPoint(&position, fcb)) {
        fprintf(stderr, "Error finding entry in the file control block.\n");
        return -4;
    }

    /*
     * order of file attributes:
     *      type    name    start
     */

    fcb[position++] = type;

    for (unsigned int i = 0; i < strlen(name); i++) {
        fcb[i + position] = name[i];
    }

    position += MAX_DIRNAME - 1;

    char* _start = encode_int(*start);

    for (int i = 0; i < START; i++) {
        fcb[i + position] = _start[i];
    }

    position += START;

    if (fcb[position + 1] == '\0') {
        fcb[position] = ENTRY_END;
    }

    if (put_block(fcBlockID, fcb)) {
        fprintf(stderr, "Error creating file control block.\n");
        return -5;
    }

    return 0;
}
Ejemplo n.º 11
0
void UVDGBObject::debugPrint()
{
	printf_plugin_debug("\n\n");

	uv_addr_t entryPoint = 0;
	UV_DEBUG(getEntryPoint(&entryPoint));
	printf_plugin_debug("entry point: 0x%08X\n", entryPoint);

	/*
	FIXME: this causes a crash
	uvd_bool_t bIsNintendoLogo = false;
	UV_DEBUG(isNintendoLogo(&bIsNintendoLogo));
	printf_plugin_debug("is nintendo logo: %d\n", bIsNintendoLogo);
	*/

	std::string title;
	UV_DEBUG(getTitle(title));
	printf_plugin_debug("title: %s\n", title.c_str());

	uint32_t manufacturerCode = 0;
	UV_DEBUG(getManufacturerCode(&manufacturerCode));
	printf_plugin_debug("manufacturer code: 0x%08X\n", manufacturerCode);

	/*
	UV_DEBUG(getCGBFlags(uint8_t *out));

	UV_DEBUG(getNewLicenseeCode(uint16_t *out));

	UV_DEBUG(getSGBFlags(uint8_t *out));

	UV_DEBUG(isSGBEnabled(uvd_bool_t *out));

	UV_DEBUG(getCartridgeType(uint8_t *out));
	*/

	uint32_t ROMSize = 0;
	UV_DEBUG(getROMSize(&ROMSize));
	printf_plugin_debug("ROM size (bytes): 0x%08X\n", ROMSize);
	uint8_t ROMSizeRaw = 0;
	UV_DEBUG(getROMSizeRaw(&ROMSizeRaw));
	printf_plugin_debug("ROM size (raw): 0x%02X\n", ROMSizeRaw);

	uint32_t saveRAMSize = 0;
	UV_DEBUG(getSaveRAMSize(&saveRAMSize));
	printf_plugin_debug("Save RAM size (bytes): 0x%08X\n", saveRAMSize);
	uint8_t saveRAMSizeRaw = 0;
	UV_DEBUG(getSaveRAMSizeRaw(&saveRAMSizeRaw));
	printf_plugin_debug("save RAM size (raw): 0x%02X\n", saveRAMSizeRaw);

	/*
	UV_DEBUG(getDestinationCode(uint8_t *out));

	UV_DEBUG(getOldLicenseeCode(uint8_t *out));

	UV_DEBUG(getMaskROMVersioNumber(uint8_t *out));
	*/

	uvd_bool_t headerChecksumValid = false;
	uint8_t headerChecksumFromFile = 0;
	uint8_t headerChecksumComputed = 0;
	UV_DEBUG(getHeaderChecksum(&headerChecksumFromFile));
	UV_DEBUG(computeHeaderChecksum(&headerChecksumComputed));
	UV_DEBUG(isHeaderChecksumValid(&headerChecksumValid));
	printf_plugin_debug("header checksum, computed: 0x%02X, from file: 0x%02X, valid: %d\n",
			headerChecksumComputed, headerChecksumFromFile, headerChecksumValid);

	uvd_bool_t globalChecksumValid = false;
	uint16_t globalChecksumFromFile = 0;
	uint16_t globalChecksumComputed = 0;
	UV_DEBUG(getGlobalChecksum(&globalChecksumFromFile));
	UV_DEBUG(computeGlobalChecksum(&globalChecksumComputed));
	UV_DEBUG(isGlobalChecksumValid(&globalChecksumValid));
	printf_plugin_debug("global checksum, computed: 0x%04X, from file: 0x%04X, valid: %d\n",
			globalChecksumComputed, globalChecksumFromFile, globalChecksumValid);

	printf_plugin_debug("\n\n");
}
Ejemplo n.º 12
0
void main (int argc, char **argv)
{

   int fd;
   char *mmapped;
   int rc;
   struct stat stbuf;
   int filesize;
   char *filename = argv[1];
   struct mach_header *mh;
   int i,j ;
   int magic;
   char *sysent = NULL;
   char *mach = NULL;
   char *xnuSig = NULL;
   int showUNIX = 1, showMach = 1;
   int suppressEnosys = 1;
   int kexts = 0;

   if (!filename) { fprintf (stderr,"Usage: joker _filename_\n", argv[0]);
		    fprintf (stderr," _filename_ should be a decrypted iOS kernelcache. Tested on 3.x-4.x-5.x-6.0\n"); 
		    fprintf (stderr, "Stable version (no symbolification/sysctl/etc here yet)\n"); exit(0);}


   rc = stat(filename, &stbuf);

   if (rc == -1) { perror ("stat"); exit (1); }

   filesize = stbuf.st_size;

   fd = open (argv[1], O_RDONLY);
   if (fd < 0) { perror ("open"); exit(2);}

   mmapped = mmap(NULL,
             filesize,  // size_t len,
             PROT_READ, // int prot,
             MAP_SHARED | MAP_FILE,  // int flags,
             fd,        // int fd,
             0);        // off_t offset);

   if (!mmapped) { perror ("mmap"); exit(3);}

   
   processFile(mmapped);

   
   mh =  (struct mach_header *) (mmapped);
  
   switch (mh->magic)
	{
		case 0xFEEDFACE:
			/* Good, this is a Mach-O */

			if (mh->cputype == 12) /* ARM */
			 {
			   // This is an ARM binary. Good.
			   printf ("This is an ARM binary. Applying iOS kernel signatures\n");
			 }
			break;

		case 0xbebafeca:	
			fprintf (stderr, "This is an Intel FAT binary, but I can't handle these yet\n");
			exit(5);
		default:
			fprintf(stderr, "I have no idea how to handle a file with a magic of %p\n", magic); exit(6);

	}
   

   printf ("Entry point is 0x%llx..", getEntryPoint());


   for  (i = 0;
         i < filesize-50;
         i++)
	{
	   
	   if (!xnuSig && memcmp(&mmapped[i], XNUSIG, strlen(XNUSIG)) == 0)
		{
		char buf[80];
		  xnuSig = mmapped + i + strlen(XNUSIG);
		memset(buf, '\0', 80);
		strncpy (buf, xnuSig, 40);

		// The signature we get is from a panic, with the full path to the
                // xnu sources. Remove the "/" following the XNU version. Because the
                // memory is mmap(2)ed read only, we have to copy this first.

		char *temp = strstr(buf, "/");
		if (temp) {
		  *temp = '\0';
		}

		xnuSig = buf;
		
		printf ("..This appears to be XNU %s\n", xnuSig);


		}

	   if (memcmp(&mmapped[i], SIG1, 20) == 0)
		{
	  	    if (memcmp(&mmapped[i+24], SIG1_SUF, 16) == 0)
			{
		          printf ("Sysent offset in file/memory (for patching purposes):  %p/%p\n",i-8,findAddressOfOffset(i -8));  
			  sysent = mmapped + i - 24 ; 
	//		  if (xnuSig) break;
			}
		}

	if (showMach)
	{
	   if (! mach &&
               (memcmp(&mmapped[i], &mmapped[i+40], 40 ) == 0) &&
	       (memcmp(&mmapped[i], &mmapped[i+32], 32 ) == 0) &&
	       (memcmp(&mmapped[i], &mmapped[i+24], 24 ) == 0) &&
	       (memcmp(&mmapped[i], &mmapped[i+16], 16) == 0) &&
	       (memcmp(&mmapped[i], &mmapped[i+24], 24) == 0) &&
	       (memcmp(&mmapped[i], &mmapped[i+8], 8 ) == 0) &&
	       (  (!*((int *) &mmapped[i])) &&  *((int *) &mmapped[i+4]))
	      )  
	      {
		  printf ("mach_trap_table offset in file/memory (for patching purposes): 0x%x/%p\n", i,findAddressOfOffset(i));
		  mach = &mmapped[i];
		  dumpMachTraps (mach);
		}

	   } // end showMach
	} // end for i..


    if (!xnuSig) { fprintf (stderr, "This doesn't seem to be a kernel!\n"); exit (7);}


	if (showUNIX)
	{
    	 if (!sysent) { fprintf (stderr, "Unable to find sysent!\n"); exit(8);}
	 if (memcmp(&mmapped[i], "syscall\0exit", 12) == 0)
	  {
	   //	syscall_names = &mmapped[i];

		printf ("Syscall names are @%x\n", i);
	  }

    if (suppressEnosys)
	{
	  int enosys = * ((int *) (sysent + 20 + 24*4));
	  printf ("Suppressing enosys (%p)\n", enosys);

	}

    for (i = 0; i < SYS_MAXSYSCALL  ; i++)
	{
	  int suppress = 0;
	  int thumb = 0;
	  int addr = * ((int *) (sysent + 20 + 24*i));
	
	  
	  if (addr == *((int *)(sysent + 20 + 24 * 8)))
		suppress =1;
	

	  if ((addr % 4) == 1) { addr--; thumb++; }
	  if ((addr % 4) == -3) { addr--; thumb++; }

  	  if (!suppress)
	    printf ("%d. %-20s %x %s\n", i,syscall_names[i], addr, (thumb? "T": "-"));

	  // skip to next post null byte - unfortunately wont work due to optimizations
	  // putting some of the system call name strings elsewhere (in their first appearance
          // in the binary)

	  //  for (; *syscall_names; syscall_names++);
	  //  syscall_names++;
	}
	  } // showUNIX

	// Do KEXTs

	// To do the kexts, we load the dictionary of PRELINK_INFO
	{
		char *kextPrelinkInfo = (char *) malloc(1000000);
		CFDictionaryRef	dict;
		char *kextNamePtr;
		char *kextLoadAddr;
		char kextName[256];
		char loadAddr[16];
		char *temp = kextPrelinkInfo;

		extern char *g_SegName;

		g_SegName = "__PRELINK_INFO";

		void *seg = MachOGetSection("__PRELINK_INFO");

		
	
		kextPrelinkInfo = (char *) (mmapped + MachOGetSegmentOffset(seg));

		temp = kextPrelinkInfo;
		kextNamePtr = strstr(temp,"CFBundleName</key>");

		// This is EXTREMELY quick and dirty, but I can't find a way to load a CFDictionary
		// directly from XML data, so it will do for now..

		while (kextNamePtr) {
			temp = strstr(kextNamePtr, "</string>");
			// overflow, etc..
			memset(kextName, '\0', 256);
			strncpy (kextName, kextNamePtr + 26, temp - kextNamePtr - 26);


			printf("Kext: %s ", kextName);
			temp += 15;

	//		_PrelinkExecutableLoadAddr
			kextNamePtr = strstr(temp, "CFBundleIdentifier");
			if (kextNamePtr)
			{
				temp = strstr(kextNamePtr,"</string>");
				memset(kextName,'\0',256);
				strncpy(kextName, kextNamePtr + 32, temp - kextNamePtr - 32);
				
				printf ("(%s)\n", kextName);
			}
			kextNamePtr = strstr(temp,"CFBundleName</key>"); 

			kexts++;
	
			

			
		
		}

		
	}
	
	printf("Got %d kexts. done\n", kexts);

}