HTML

Hackstock

Hack the planet! Hackers unite!

Címkék

Címkefelhő

A nagy fogyás

2008.02.02. 14:30 :: theshadow

Elvadult pillanatomban a Mach-O file formátumának leírását kerestem. Nem kellett sokáig kutakodnom, mert nyílt és az Apple szépen leírja az elképzeléseit és bárki számára elérhető itt.

Ami felkeltette az érdeklődésemet éppen a dokumentum végén található: Universal Binaries. Az unverzális bináris állományok lényege, hogy több architektúrára fordított program egy file-ban helyezkedik el és az operációs rendszer a neki megfelelőt tölti be és futtatja.

Az univerzális állományok 0xCAFEBABE - small endian - intereg szignaturával kezdődnek és a következő integer a különböző architekturális bináris képállományok számát adja meg.

struct fat_header
   {
   uint32_t magic;
   uint32_t nfat_arch;
};

Ez után szerepel nfat_arch számú fat_arch struktúra.

struct fat_arch
   {
   cpu_type_t cputype;
   cpu_subtype_t cpusubtype;
   uint32_t offset;
   uint32_t size;
   uint32_t align;
};

Most a CPU típus az érdekes csupán, az altípus lényegtelen. A típusleíró intereg első 24 bitjére kell koncentrálnunk; ez fölött (a 24. bit) jelzi, hogy 64 bites. A következő értékek fordulhatnak elő:

  • 7: x86
  • 12: ARM (iPhone!!!)
  • 18: PPC

Az offset és size a megfelelő állománykép helyét adja meg a file-ban.
Ezen a ponton gondolkoztam el: ha Intel (én spec. AMD) processzoron futtatom a Leopard-ot, akkor szükségem van a PPC-s programrészletekre? Nem. Tehát ha a belső képállományt kiemelném, akkor működőképes maradna a program? A Mach-O szabványleírás szerint igen.
Egy próbától senkinek sem eshet baja. Erre dobtam össze egy egyszerű programot Java-ban.

package org.hackstock.tbl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class TheBiggestLoser {

    private final static String ParIntel = "Intel";
    private final static String ParPPC = "PPC";
    private final static String ParARM = "ARM";
    private final static int aIntel = 7;
    private final static int aARM = 12;
    private final static int aPPC = 18;
   
    public static void main(String[] args) {
        if (args.length != 2 && !(ParIntel.equals(args[0]) || ParPPC.equals(args[0]) || ParARM.equals(args[0]))) {
            System.out.println("Usage:\n java -cp ... org.hackstock.tbl.TheBiggestLoser <Intel | PPC | ARM> <dir to scan>");
        }else {
            int arch = 0;
            if (ParIntel.equals(args[0])) {
                arch = aIntel;
            }else if (ParPPC.equals(args[0])) {
                arch = aPPC;
            }else {
                arch = aARM;
            }
            File file = new File(args[1]);
            if (file.exists()) {
                new TheBiggestLoser(arch,file);
            }else {
                System.out.println("The file or directory doesn't exist.");
            }
        }
    }

    private TheBiggestLoser(int arch,File dir) {
        if (dir.isFile()) {
            processFile(arch, dir);
        }else {
            System.out.println("Scanning: "+dir.getAbsolutePath());
            File[] child = dir.listFiles();
            for (int i = 0; i < child.length; ++i) {
                if (child[i].isDirectory()) {
                    new TheBiggestLoser(arch,child[i]);
                }else if (child[i].isFile()) {
                    processFile(arch,child[i]);
                }
            }
        }
    }
   
    private void processFile(int arch,File file) {
        try {
            RandomAccessFile raf = new RandomAccessFile(file,"rw");
            try {
                if (raf.length() > 8) {
                    int fat = raf.readInt();
                    if (fat == 0xcafebabe) {
                        System.out.print("\tProcessing: "+file.getName()+" ... ");
                        System.out.print("size: "+(raf.length()+4)+" - ");
                        int nfatarchs = raf.readInt();
                        int offset, size;
                        offset = size = -1;
                        for (int i = 0; i < nfatarchs; ++i) {
                            if ((raf.readInt() & 0xFFFFFF) == arch) {
                                raf.readInt();
                                offset = raf.readInt();
                                size = raf.readInt();
                                raf.readInt();
                            }else {
                                raf.readInt();
                                raf.readInt();
                                raf.readInt();
                                raf.readInt();
                            }
                        }
                        if (offset != -1 && size != -1) {
                            System.out.print("Size of content: "+size);
                            byte[] buffer = new byte[size];
                            raf.seek(offset);
                            raf.read(buffer, 0, size);
                            raf.seek(0);
                            raf.write(buffer, 0, size);
                            raf.setLength(size);
                        }else {
                            System.out.print("Specified content not found!");
                        }
                       
                        System.out.println();
                    }
                }
                   
            } catch (IOException e1) {
                e1.printStackTrace();
            }
           
            try {
                raf.close();
            } catch (IOException e) {
            }
        } catch (FileNotFoundException e) {
        }
    }
}

A futtatható JAR file-t innen lehet letölteni.
A használatával legyünk óvatosak. Az iTunes-on, Microsoft Messenger-en próbáltam ki és tökéletesen működik. A viszonyleg kevés ellenőrzés miatt lehetőleg ne akadjon össze java file-okkal, mert azokat tönkre teheti.
Működését tekintve egy file-t vagy egy könyvtárat fésül át és minden univerzális binárisból a paraméterben meghatározott speciális binárist emeli ki.
Vigyázat: az eredeti állomány az új tartalommal íródik felül!
Indítása parancssorból a következőképpen:

java -cp TheBiggestLoser.jar org.hackstock.tbl.TheBiggestLost Intel /Applications/iTunes.app

Szólj hozzá!

Címkék: macosx x86

A bejegyzés trackback címe:

https://hackstock.blog.hu/api/trackback/id/tr14322100

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

Nincsenek hozzászólások.