Function Hooking For OSX and Linux
Function Hooking For OSX and Linux
dbgrady.files.wordpress.com
WTF is an ABI ?
WTF is an Application
Binary
Interface ?
alignment
thomasgroup.com
calling convention
arianlim.wordpress.com
object file and
library formats
tandemfs.org
hierarchy of specs
topatoco.com
System V ABI (271 pages)
System V ABI AMD64 Architecture Processor
Supplement (128 pages)
System V ABI Intel386 Architecture Processor
Supplement (377 pages)
based on
thomasgroup.com
end of argument area must be
aligned on a 16byte boundary.
arianlim.wordpress.com
• function arguments from left to right live in:
%rdi, %rsi, %rdx, %rcx, %r8, %r9
tandemfs.org
steverubel.typepad.com
ELF Objects
en.wikipedia.org
ELF Objects
• ELF objects have headers
• elf header (describes the elf object)
• program headers (describes segments)
• section headers (describes sections)
• libelf is useful for wandering the elf object extracting
information.
• the executable and each .so has its own set of data
ELF Object sections
• .text - code lives here
• .plt - stub code that helps to “resolve”
absolute function addresses.
• .got.plt - absolute function addresses; used
by .plt entries.
• .debug_info - debugging information
• .gnu_debuglink - checksum and filename for
debug info
ELF Object sections
• .dynsym - maps exported symbol names to
offsets
• .dynstr - stores exported symbol name
strings
• .symtab - maps symbol names to offsets
• .strtab - symbol name strings
• more sections for other stuff.
vanachteren.net
Mach-O Objects
developer.apple.com
Mach-O Objects
• Mach-O objects have load commands
• header (describes the mach-o object)
• load commands (describe layout and linkage info)
• segment commands (describes sections)
• dyld(3) describes some apis for touching mach-o
objects
• the executable and each dylib/bundle has its own set
of data
Mach-O sections
• __text - code lives here
• __symbol_stub1 - list of jmpq instructions
for runtime dynamic linking
• __stub_helper - stub code that helps to
“resolve” absolute function addresses.
• __la_symbol_ptr - absolute function
addresses; used by symbol stub
Mach-O sections
• symtabs do not live in a segment, they have
their own load commands.
• LC_SYMTAB - holds offsets for symbol
table and string table.
• LC_DYSYMTAB - a list of 32bit offsets into
LC_SYMTAB for dynamic symbols.
blog.makezine.com
nm
% nm /usr/bin/ruby
000000000048ac90 t Balloc
0000000000491270 T Init_Array
0000000000497520 T Init_Bignum
000000000041dc80 T Init_Binding
symbol symbol names
“value” 000000000049d9b0 T Init_Comparable
000000000049de30 T Init_Dir
00000000004a1080 T Init_Enumerable
00000000004a3720 T Init_Enumerator
00000000004a4f30 T Init_Exception
000000000042c2d0 T Init_File
0000000000434b90 T Init_GC
objdump
% objdump -D /usr/bin/ruby
callq *%rbx
callq 0xdeadbeef
while (are_moar_bytes()) {
curr_ins = next_ins;
next_ins = get_next_ins();
if (curr_ins->type == INSN_CALL) {
if ((hook_me - next_ins) == curr_ins->displacement) {
/* found a call hook_me!*/
rewrite(curr_ins->displacement, (replacement_fn - next_ins));
return 0;
}
}
}
... right?.....
lemur.com
32bit displacement
• overwriting an existing call with another call
• stack will be aligned
• args are good to go
• can’t redirect to code that is outside of:
• [rip + 32bit displacement]
• you can scan the address space looking for
an available page with mmap, though...
Doesn’t work for all
.got.plt entry
Initially, the .got.plt entry contains
the address of the instruction after
the jmp. 0x7ffff7afd6e6
How runtime dynamic
linking works (elf)
.got.plt entry
An ID is stored and the rtld is
invoked.
0x7ffff7afd6e6
How runtime dynamic
linking works (elf)
.got.plt entry
rtld writes the address of
rb_newobj to the .got.plt entry.
0x7ffff7b34ac0
How runtime dynamic
linking works (elf)
.got.plt entry
rtld writes the address of
rb_newobj to the .got.plt entry.
0x7ffff7b34ac0
calls to the PLT entry jump
immediately to rb_newobj now
that .got.plt is filled in.
rs.tacklewarehouse.com
Hook the GOT
mach-o
me
what else is left?
inline functions.
add_freelist
• Can’t hook because add_freelist is inlined:
static inline void
add_freelist(p)
RVALUE *p;
{
p->as.free.flags = 0;
p->as.free.next = freelist;
freelist = p;
}
thomasgroup.com
calling convention
arianlim.wordpress.com
Isn’t ready? What?
• The 64bit ABI says that the stack must be
aligned to a 16byte boundary after any/all
arguments have been arranged.
• Since the overwrite is just some random
mov, no way to guarantee that the stack is
aligned.
• If we just plop in a call instruction, we
won’t be able to arrange for arguments to
get put in the right registers.
• So now what?
jmp
• Can use a jmp instruction.
• Transfer execution to an assembly stub
generated at runtime.
• recreate the overwritten instruction
• set the system up to call a function
• do something good/bad
• jmp back when done to resume execution
picasaweb.google.com/lh/photo/-R3BPlqOq8MfQGFTduIqCA
checklist
• save and restore caller/callee saved
registers.
• align the stack.
• recreate what was overwritten.
• arrange for any arguments your
replacement function needs to end up in
registers.
• invoke your code.
• resume execution as if nothing happened.
this instruction updates the freelist and comes from
add_freelist:
108 /custom/ree/lib/ruby/1.8/x86_64-linux/stringio.so:0:__node__
14 test2.rb:3:String
2 /custom/ree/lib/ruby/1.8/x86_64-linux/stringio.so:0:Class
1 test2.rb:4:StringIO
1 test2.rb:4:String
1 test2.rb:3:Array
1 /custom/ree/lib/ruby/1.8/x86_64-linux/stringio.so:0:Enumerable
memprof.com
a web-based heap visualizer and leak analyzer
memprof.com
a web-based heap visualizer and leak analyzer
memprof.com
a web-based heap visualizer and leak analyzer
memprof.com
a web-based heap visualizer and leak analyzer
memprof.com
a web-based heap visualizer and leak analyzer
memprof.com
a web-based heap visualizer and leak analyzer
community.devexpress.com
config.middleware.use(Memprof::Tracer)
{
"time": 4.3442, total time for request
"mysql": {
"queries": 3, 3 mysql queries
"time": 0.00109302
},
"gc": {
"calls": 8, 8 calls to GC
"time": 2.04925 2 secs spent in GC
},
config.middleware.use(Memprof::Tracer)
"objects": {
"created": 3911103, 3 million objs created
"types": {
"none": 1168831, 1 million method calls
"object": 1127, object instances
"float": 627,
"string": 1334637, lots of strings
"array": 609313, lots of arrays
"hash": 3676,
"match": 70211 regexp matches
}
}
}
smiley-faces.org
mindfulsecurity.com
evil lives
http://github.com/ice799/memprof/tree/dnw
• makes ruby faster!11!!1
• hooks read syscall
• looks for magic cookie (JOE)
• turns off GC
• Ruby is fast.
it makes ruby faster!!1!
look a bullshit
benchmark!
it makes ruby faster!!1!
#NORMAL RUBY!!!!11!!
Concurrency Level: 10
Time taken for tests: 7.462 seconds
Complete requests: 200
Failed requests: 0
Write errors: 0
Requests per second: 26.80 [#/sec] (mean)
Time per request: 373.108 [ms] (mean)
Time per request: 37.311 [ms] (mean, across all concurrent requests)
it makes ruby faster!!1!
# fast0r RUBY!!!11!111
[joe@mawu:/Users/joe/code/defcon]% ab -c 10 -n 200 http://blah:4567/hi/JOE
Concurrency Level: 10
Time taken for tests: 6.594 seconds
Complete requests: 200
Failed requests: 0
Write errors: 0
Requests per second: 30.33 [#/sec] (mean)
Time per request: 329.708 [ms] (mean)
Time per request: 32.971 [ms] (mean, across all concurrent requests)
you can do anything
• this example is stupid, but you can do
anything.
• hook read/write and phone home with
data.
• fork a backdoor when a specific cookie is
seen
• whatever
break.com
zanyvideos.com
injectso
• ptrace(2)
• allows you to view and modify the
register set and address space of another
process
• permissions on memory are ignored
fucking injectso, how
does it work?
• attach to target process using ptrace
• save a copy of a small piece of the program
stack.
• save a copy of the register set
• create a fake stack frame with a saved return
address of 0
fucking injectso, how
does it work?
• set register set to point at dlopen
• rip = &dlopen
• rdi = dso name
• rsi = mode
• let er rip, waitpid and it’ll segfault on return
to 0.
• restore stack, register set, resume as
normal.
ptrace evil dso
• remote allocating • getting the user to
memory is a pain in use your library
the ass. might be hard.
customdynamics.com
customdynamics.com
buycostumes.com
emeraldinsight.com
how to defend against it
• NX bit - call mprotect
• strip debug information - mostly prebuilt binaries
• statically link everything - extremely large binaries
• put all .text code in ROM - maybe?
• don’t load DSOs at runtime - no plugins, though
• disable ptrace - no gdb/strace.
• check /proc/<pid>/maps - word.
slashgear.com
my future research:
exploring alternative
binary formats.
slayerinc.com
globalhealthandfitness.com
alignment
thomasgroup.com
calling convention
arianlim.wordpress.com
object file and
library formats
tandemfs.org
questions?
joe damato
@joedamato
timetobleed.com
http://timetobleed.com/string-together-global-offset-tables-to-build-a-ruby-memory-profiler/
http://timetobleed.com/hot-patching-inlined-functions-with-x86_64-asm-metaprogramming/
http://timetobleed.com/rewrite-your-ruby-vm-at-runtime-to-hot-patch-useful-features/
http://timetobleed.com/dynamic-linking-elf-vs-mach-o/
http://timetobleed.com/dynamic-symbol-table-duel-elf-vs-mach-o-round-2/
tallteacher.files.wordpress.com
“Interesting Behavior of
OS X”