schnauzer
is both library and tool for parsing mach-o files, printing symbol table, used dynamic libraries, relative paths, relocation entries, e.t.c.. See full list of commands.
match
blocks for any type of load commandshell
cargo install schnauzer
Call to schnauzer
should have the next pattern:
shell
schnauzer [CMD] path_to_binary
Where CMD
is optional. See Supported commands section
Specify -h
or --help
with or without specify subcommand to see description and supported arguments of the subcommand.
You also can specify path with -p
or --path
(But this not required)
schnauzer lc FILE [--path <FILE>] [--help] [--arch <NAME>] [--short] [--noidx]
schnauzer syms FILE [--path <FILE>] [--help] [--arch <NAME>] [--short] [--noidx]
schnauzer rpaths FILE [--path <FILE>] [--help] [--arch <NAME>] [--short] [--noidx]
schnauzer dylibs FILE [--path <FILE>] [--help] [--arch <NAME>] [--short] [--noidx]
schnauzer segs FILE [--path <FILE>] [--help] [--arch <NAME>] [--segs] [--sects] [--short] [--noidx]
schnauzer fat FILE [--path <FILE>] [--help] [--arch <NAME>]
schnauzer headers FILE [--path <FILE>] [--help] [--arch <NAME>] [--short] [--noidx]
schnauzer rel FILE [--path <FILE>] [--help] [--arch <NAME>]
schnauzer data FILE [--path -p <FILE>] [--help -h] [--arch -a <NAME>] --sect -s <segname sectname>
```shell
schnauzer pathtobinary
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
...
```
```shell
schnauzer lc pathtobinary
Arch #0 (Arch: x8664, File type: Exec, Flags: 0x00200085):
cmd: LCSEGMENT64 cmdsize: 72
segname: _PAGEZERO
vmaddr: 0x0000000000000000
vmsize: 0x0000000100000000
fileoff: 0
filesize: 0
maxprot: 0x00000000
initprot: 0x00000000
nsects: 0
flags: 0x00000000
cmd: LCSEGMENT64 cmdsize: 552
segname: __TEXT
vmaddr: 0x0000000100000000
vmsize: 0x0000000000004000
fileoff: 0
```
```shell
schnauzer syms pathtobinary
Arch #1 (Arch: x8664, File type: Exec, Flags: 0x00200085):
[0] Stab(Nopt) radr://5614542
[1] External mhexecuteheader
Section: 1, ndesc: 16, Address: 0x0000000100000000
[2] External _DefaultRuneLocale
ndesc: 256, nvalue: 0
[3] External _error
ndesc: 256, nvalue: 0
[4] External maskrune
ndesc: 256, nvalue: 0
[5] External stackchkfail
ndesc: 256, nvalue: 0
[6] External _stackchk_guard
...
```
```shell
schnauzer rpaths pathtobinary
Arch #0 (Arch: arm64, File type: Exec, Flags: 0x04a18085):
[0] /usr/lib/swift
[1] @loaderpath/Frameworks
[2] @loaderpath/Frameworks
[3] @executablepath/Frameworks
[4] /usr/lib/swift
[5] @executablepath/Frameworks
[6] @loader_path/Frameworks
```
```shell
schnauzer dylibs pathtobinary
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) ```
```shell
schnauzer segs pathtobinary ```
``` 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
...
```shell
schnauzer fat pathtobinary
[0] Arch: x86_64, Offset: 16384, Size: 70080, Align: 14
[1] Arch: arm64e, Offset: 98304, Size: 53488, Align: 14
```
```shell
schnauzer headers pathtobinary
[0] Magic: cffaedfe, Arch: x8664, Capabilities: 0x00, File type: Exec, Commands: 17, Size of commands: 1544, Flags: 0x00200085
Flags(detailed):
MHNOUNDEFS
MHDYLDLINK
MHTWOLEVEL
MHPIE
[1] Magic: cffaedfe, Arch: arm64e, Capabilities: 0x80, File type: Exec, Commands: 18, Size of commands: 1368, Flags: 0x00200085
Flags(detailed):
MHNOUNDEFS
MHDYLDLINK
MHTWOLEVEL
MH_PIE
```
```shell
schnauzer rel pathtobinary
_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
```
```shell
schnauzer data pathtobinary -s _TEXT _cstring
Arch #0 (Arch: x8664, 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|
```
toml
[dependencies]
schnauzer = "0.3.2"
Simple debug print
```rust use schnauzer::ObjectType; use schnauzer::Parser; use std::path::Path;
fn main() { let mut args = std::env::args(); let execname = 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); } ```
Using AutoEnumFields
derive (code taken from src/main.rs
)
rust
let h = macho.header();
for field in h.all_fields() {
out_dashed_field(field.name, field.value, level);
}
You may email me: arsynthdev@gmail.com