#mach-o #binary #macho #derive

schnauzer-derive

为schnauzer库提供的衍生功能

1个不稳定版本

0.1.0 2023年5月7日

#macho中排名第7


2个crate中使用(通过schnauzer

MIT/Apache

6KB
119

Schnauzer

demo

schnauzer是一个解析mach-o文件的库和工具,用于打印符号表、使用动态库、相对路径、重定位条目等。查看命令列表

更新日志

库功能

  • 零拷贝。不将整个二进制文件加载到内存中。使用迭代器列出可能的大量项目
  • 端序感知
  • 实现了自动字段枚举的衍生宏,例如,非常方便用于打印任意加载命令。甚至不需要为任何类型的加载命令编写大的match
  • 以彩色打印文件结构,以改善用户体验

安装

cargo install schnauzer

参数

调用schnauzer应具有以下模式

schnauzer [CMD] path_to_binary

其中CMD是可选的。请参阅支持的命令部分

可以使用-h--help指定子命令,以查看子命令的描述和支持的参数。

您还可以使用-p--path指定路径(但这不是必需的)

支持的命令

默认

# Prints almost all binary info
schnauzer path_to_binary
Fat arch:
 |*cputype: 16777223
 |*cpusubtype: 3
 |*offset: 16384
 |*size: 70080
 |*align: 14
 |*Mach header: 
   |*magic: 0xcffaedfe
   |*cputype: 16777223
   |*cpusubtype: 3
   |*filetype: Exec
   |*ncmds: 17
   |*sizeofcmds: 1544
   |*flags: 0x00200085
   |*reserved: 0x00000000
   |*Load commands: 
   [0] cmd: LC_SEGMENT_64 cmdsize: 72
     |*segname: __PAGEZERO
     |*vmaddr: 0x0000000000000000
     |*vmsize: 0x0000000100000000
     |*fileoff: 0
     |*filesize: 0
     |*maxprot: 0x00000000
     |*initprot: 0x00000000
     |*nsects: 0
     |*flags: 0x00000000
...

lc

# Prints load commands
schnauzer lc path_to_binary
Arch #0 (Arch: x86_64, File type: Exec, Flags: 0x00200085):
cmd: LC_SEGMENT_64 cmdsize: 72
 segname: __PAGEZERO
 vmaddr: 0x0000000000000000
 vmsize: 0x0000000100000000
 fileoff: 0
 filesize: 0
 maxprot: 0x00000000
 initprot: 0x00000000
 nsects: 0
 flags: 0x00000000
cmd: LC_SEGMENT_64 cmdsize: 552
 segname: __TEXT
 vmaddr: 0x0000000100000000
 vmsize: 0x0000000000004000
 fileoff: 0

syms

# Prints symtab
schnauzer syms path_to_binary
Arch #1 (Arch: x86_64, File type: Exec, Flags: 0x00200085):
[0] Stab(Nopt) radr://5614542
[1] External __mh_execute_header
Section: 1, n_desc: 16, Address: 0x0000000100000000
[2] External __DefaultRuneLocale
n_desc: 256, n_value: 0
[3] External ___error
n_desc: 256, n_value: 0
[4] External ___maskrune
n_desc: 256, n_value: 0
[5] External ___stack_chk_fail
n_desc: 256, n_value: 0
[6] External ___stack_chk_guard
...

rpaths

# Prints relative paths
schnauzer rpaths path_to_binary
Arch #0 (Arch: arm64, File type: Exec, Flags: 0x04a18085):
[0] /usr/lib/swift
[1] @loader_path/Frameworks
[2] @loader_path/Frameworks
[3] @executable_path/Frameworks
[4] /usr/lib/swift
[5] @executable_path/Frameworks
[6] @loader_path/Frameworks

dylibs

# Prints used dynamic libraries
schnauzer dylibs path_to_binary
Arch #1 (Arch: x86_64, File type: Exec, Flags: 0x00200085):
[0] /usr/lib/libSystem.B.dylib (Timestamp: 2, Current version: 1311.0.0, Compatibility version: 1.0.0)

Arch #2 (Arch: arm64e, File type: Exec, Flags: 0x00200085):
[0] /usr/lib/libSystem.B.dylib (Timestamp: 2, Current version: 1311.0.0, Compatibility version: 1.0.0)

segs

# Prints all the segments with sections
schnauzer segs path_to_binary
Usage:

        schnauzer segs path_to_binary [--segs] [--sects] [--short] [--noidx]

        --segs - Print only segments
        --sects - Print only sections
        --short - Print only values and only identifying fields
        --noidx - Disable printing indices
...
[1] Segment (segname: __TEXT, vmaddr: 0x0000000100000000, vmsize: 0x0000000000004000, fileoff: 0, filesize: 16384, maxprot: 0x00000005, initprot: 0x00000005, nsects: 6, flags: 0x00000000):
  Section #1 __text Segment __TEXT:
  |*addr: 0x000000010000335c
  |*size: 0x000000000000094f
  |*offset: 13148
  |*align: 2
  |*reloff: 0
  |*nreloc: 0
  |*flags: 0x80000400
  |*reserved1: 0
  |*reserved2: 0
  |*reserved3: 0
...

fat

# Prints the fat archs
schnauzer fat path_to_binary
[0] Arch: x86_64, Offset: 16384, Size: 70080, Align: 14
[1] Arch: arm64e, Offset: 98304, Size: 53488, Align: 14

headers

# Prints headers
schnauzer headers path_to_binary
[0] Magic: cffaedfe, Arch: x86_64, Capabilities: 0x00, File type: Exec, Commands: 17, Size of commands: 1544, Flags: 0x00200085
Flags(detailed):
MH_NOUNDEFS
MH_DYLDLINK
MH_TWOLEVEL
MH_PIE
[1] Magic: cffaedfe, Arch: arm64e, Capabilities: 0x80, File type: Exec, Commands: 18, Size of commands: 1368, Flags: 0x00200085
Flags(detailed):
MH_NOUNDEFS
MH_DYLDLINK
MH_TWOLEVEL
MH_PIE

rel

# Prints relocation entries
schnauzer rel path_to_binary
__TEXT __text (5 entries)
address  pcrel length extern type scattered symbolnum/value 
000000b0 1     2      1      2    false     10              
000000ac 0     2      1      4    false     2               
000000a8 1     2      1      3    false     2               
0000009c 0     2      1      4    false     1               
00000098 1     2      1      3    false     1               
__DATA __const (1 entries)
address  pcrel length extern type scattered symbolnum/value 
00000000 0     3      1      0    false     4               
__DWARF __debug_info (16 entries)
address  pcrel length extern type scattered symbolnum/value 
000004c2 0     3      0      0    false     1               
000004ba 0     3      0      0    false     1               
00000499 0     3      0      0    false     1               
00000491 0     3      0      0    false     1               
00000477 0     3      0      0    false     1              

data

# Prints hex dump
schnauzer data path_to_binary -s __TEXT __cstring
Arch #0 (Arch: x86_64, File type: Exec, Flags: 0x00200085):
__TEXT __cstring
0000000100003f2a 0062656c 6e737475 76007374 646f7574 |.belnstuv.stdout|
0000000100003f3a 00757361 67653a20 63617420 5b2d6265 |.usage: cat [-be|
0000000100003f4a 6c6e7374 75765d20 5b66696c 65202e2e |lnstuv] [file ..|
0000000100003f5a 2e5d0a00 2d007374 64696e00 25730072 |.]..-.stdin.%s.r|

用法

[dependencies]
schnauzer = "0.3.5"

示例

简单调试打印

use schnauzer::ObjectType;
use schnauzer::Parser;
use std::path::Path;

fn main() {
    let mut args = std::env::args();
    let _exec_name = args.next();

    let path = match args.next() {
        Some(s) => s,
        None => {
            eprintln!("Not enough arguments. Provide a valid path to binary");
            std::process::exit(1);
        }
    };
    let path = Path::new(&path);

    let parser = match Parser::build(path) {
        Ok(b) => b,
        Err(e) => {
            eprintln!("Could not create parser at '{:?}': {e}", path);
            std::process::exit(1);
        }
    };

    let object = match parser.parse() {
        Ok(o) => o,
        Err(e) => {
            eprintln!("Error while parsing: {:#?}", e);
            std::process::exit(1);
        }
    };

    handle_object(object);
}

fn handle_object(obj: ObjectType) {
    println!("***Object***");
    println!("{:#?}", obj);
}

使用AutoEnumFields衍生宏(代码取自src/main.rs

let h = macho.header();
for field in h.all_fields() {
    out_dashed_field(field.name, field.value, level);
}

联系方式

您可以给我发邮件:[email protected]

GitHub个人资料

依赖项

~1.5MB
~35K SLoC