draugr.git


draugr

~ single ELF file analysis tool
git clone https://github.com/djnnvx/draugr.git
log | files | refs | archive | README

draugr

ELF mapping and analysis tool. Written in Odin with no third-party dependencies.

Build

asdf install
odin build . -out:draugr

Usage

draugr <elf-path> [flags]
Flag Description
--info ELF summary only (class, type, machine, entry, PIE, dynamic, counts)
--sections Section header table
--segments Program header table, objdump -p style
--symbols Symbol table, nm style, static and dynamic
--map Visual memory layout
--entropy Shannon entropy, 256-byte blocks, bits per byte
--hexdump Hex dump the whole file
--checksec Hardening report: RELRO, NX, canary, PIE, RPATH, FORTIFY
--relocs Relocation table and PLT/GOT map
--code Code regions: executable sections with entropy, entry point, function starts
--call-function <sym> Load the file from memory and call one symbol
--call-args <list> Arguments for --call-function
--patch <list> In-memory patches applied before --call-function (x86-64). ;-separated: sym=ret:N, sym=jmp:target, got:sym=target
--bin-diff <file> Diff this binary's layout against a reference ELF
--json Full structured dump: header, segments, sections, dynamic, symbols, relocations, GOT, checksec
--verbose Verbose output

--hexdump, --entropy and --code each have an --<name>-out <file> variant that writes to a file instead of stdout. Flags combine, so --sections --symbols prints both.

--json covers the whole structured dump on its own and ignores the selector flags. It is rejected alongside --hexdump, --entropy, --code, --map, --bin-diff and --call-function, which are visualizations or actions with no JSON form.

Both --flag value and --flag=value work, and a single dash is accepted.

Simple examples

draugr --json /bin/ls | jq .needed
draugr --json /bin/ls | jq .checksec
draugr --json /bin/ls | jq .got.fclose       # GOT slot address, pwntools style
draugr --json /bin/ls | jq '.dynamic_entries[] | select(.tag == "RUNPATH")'
draugr --sections /bin/ls | awk '$3 == "PROGBITS"'
draugr --symbols /bin/ls | grep ' U '        # undefined imports
draugr --bin-diff v1.4.2/httpd v1.4.3/httpd  # what changed between firmware builds

Calling a function

--call-function loads the file through a memfd and calls a single symbol, without the linked object ever reaching disk. A .o is linked first with ld -shared writing straight into the memfd; a .so is written to the memfd as-is.

draugr --call-function alpha --call-args 21 ./thing.o
draugr --call-function parse --call-args s:AAAA,64 ./libvendor.so

Arguments are comma-separated: integers (decimal or 0x), or s:text to pass a pointer to a NULL-terminated string. Up to six, matching the integer argument registers. Floats and structs are not supported, and the return value is read as a 64-bit integer.