all right so Aloha and welcome to my
talk about getting cozy with auditing on
Mac OS his Matt mentioned my name is
Patrick Wardle and I've worked at a
variety of acronym places including some
government agencies currently I'm the
chief research officer at a small
start-up called digital security and
very briefly digital security we're
creating enterprise tools for the Mac
alright so what are we going to be
talking about today so we're gonna start
with an overview of auditing on Mac OS
now I'll be the first to admit that
talking about auditing might not seem
like the most sexy or interesting topic
but the reality is it's actually very
relevant in something important to talk
about
so as we'll see auditing is very useful
for both malware analysis and forensics
and if you're interested in creating
security tools we'll show how you can
utilize the auditing mechanisms built
into the operating system to build some
very powerful security tools also if you
are a hacker or if you are developing
offensive cyber security capabilities
it's very important to know what type of
auditing may be going on on the system
so that your tools your exploits your
capabilities remain undetected
well then dive into a built in auditing
mechanism or subsystem called open BSM
and we'll see that this is kind of the
de-facto auditing mechanism on mac well
then dawn on our black hats and kind of
take a more offensive turn to talk about
some vulnerabilities in the auditing
subsystem so first we'll talk about a
kernel panic and then we'll end by
talking about some more interesting bugs
in the kernel one being an information
leak and the other being an exploitable
heap overflow so let's start by talking
about auditing mechanisms on Mac OS now
first you might be wondering what is
auditing anyways and this is a question
I had when I began this research and
there's a great quote from Jonathan 11
Jonathan is the author of the very
popular Mac OS internal books highly
recommended if you're interested in iOS
and Mac OS internals and as he states in
his book he says
editing enables the recording of events
which may have security implications now
another question might be what's the
difference between logging and auditing
and this is again very valid question
so logging can be thought of a way to
kind of monitor any kind of activity so
you think you know in your application
you add a print statement or a syslog
statement you can print some value of
some variable right this doesn't
necessarily have to have security
implications auditing as I mentioned is
generally going to be logging or
recording actions that have security
implications logging is also opt-in so
if your application doesn't have printf
statements or syslog it's not going to
generate any logging auditing on the
other hand is an enabled by default and
is usually implemented at the kernel
level so for example say there's some
auditing enabled that audits login or
logout events or syslog call assist
system calls you know your application
might not want to be audited but it's
it's gonna get audited by the system
regardless why auditing briefly
mentioned from a security point of view
it's a very important thing for an
operating system to have so it can be
used very very useful for helping to
uncover or understand intrusions or even
malware infections so for example as
we'll see when events such as a new
processes started you know a new file
i/o activity perhaps even a new network
connection these are all events that can
be audited by the operating system so
obviously if a piece of malware or a
hacker gets into your system these are
all events that can be recorded and can
then help potentially uncover that
infection or intrusion now more
interesting to me though is using the
audit subsystems to create security
tools so for example and we'll talk
about some other tools later I wrote a
simple utility that's able to
generically detect ransomware on Mac OS
so all the tool does is look for the
rapid creation of encrypted files by
untrusted processes this is basically
something that ransomware does so what
the tool does is it taps into the
auditing subsystem to get processed
notification events
and also file i/o events so the audit
subsystem will now tell the tool
whenever a new process is started and
also whenever a new file is created or
modified so then all the tool has to do
is examine that file to see if it's
encrypted and then keep track of some
files and also see what process is
creating those encrypted files and then
it can generically detect all known Reds
where on Mac OS so again a very powerful
tool that's pretty easy to implement
thanks again to the auditing subsystems
so what auditing mechanisms are
available on Mac OS turns out there's
quite a few and we'll talk through all
of these kind of looking at the pros and
cons of each and also identifying any
limitations of each of these auditing
mechanisms so we'll talk about FS events
kadiebug events D trace and finally open
BSM so first up we have FS events FS
stands for file system now if you're
familiar with Linux these FS events are
pretty much similar to Linux I notifies
subsystem so as its name implies FS
events you can use this auditing
mechanism to monitor or audit for file
IO events you can do this in three easy
steps
so the first thing you do is connect to
slash dev slash FS events this is a
special device file on Mac OS you then
clone this file descriptor and specify
what events are of interest to you for
example file creations file deletions
etc etc then what you do is in a while
loop you just read off this file handle
and the kernel will deliver file i/o
events to you so let's look briefly in
code how we can implement something such
as a simple file monitor so again you
can see in the code at the very top we
call open and we open this dev /fs
events device file we then specify or
tell the colonel
what file IO events are of interest to
us and since we're writing a file maaan
utility we basically tell it hey we're
interested in everything so we set FS e
underscore report to every single
event.we then clone the file descriptor
and then we very bottom we enter a while
loop just reading forever off this file
handle and again as these file i/o
events come in the kernel will deliver
them to user mode via that file and
since we're reading off those file we
can consume and parse those events so at
the bottom for example if I touch a file
and then remove that file running this
code the file one utility we can see it
detects the touch event and also the
remove event so again pretty easy to
write a fairly fully featured Taman
utility using the FS events auditing
mechanism the next auditing mechanism I
want to talk about is the kadiebug
utility this is a built-in kernel trace
auditing capability now unlike FS events
which are limited just to file system
events the kadiebug events pretty much
trace all activity on the system and
Apple actually uses kadiebug events in a
variety of their own tools so they have
a latency tool they have another tool
called SC underscore usage which shows
system calls and then they actually have
a file mod utility called FS underscore
usage that's built into Mac OS now it's
interesting that they don't use the FS
events auditing mechanism they instead
decided to use the K debug and this is
because the Canadian ism is so much more
powerful so what happens is kadiebug
events are generated when code in the
kernel calls a macro such as kernel
underscore debug underscore constant so
on the slide for example we can see the
SIS call handler this is the interface
in the kernel where user mode code that
is making system calls will go through
and enter the kernel and we can see in
the code there is a call to the kernel
debug constant macro and this will
generate a kadiebug event so if we're
reading these events and user mode we
will get an event that assists call has
occurred so programmatically how does
one subscribe to these kadiebug events
to get these audit notifications so the
first thing we have to do is we have to
tell the kernel to enable this audit
mechanism and you do that via assist
control when you pass in the current KD
enable
value and then once it is enabled you
basically read events by again invoking
sysctl
this time with the Kern underscore KD
read TR value and this will then we get
deliver to you these kadiebug messages
from kernel mode to user mode now these
messages are compressed and encoded as
Jonathan notes but what we can do is we
can consult the trace dot codes file
which is a file that is in Mac OS and
this allows us to decode the events so
again Jonathan has created an open
source utility called kdv and so this
code for example is from his utility so
if we compile and run that utility we
can see a ton of events I mean this is
just gonna you know fulfill the screen
with all sorts of events so for example
we can see events related to the CPU
utilization mock events etc etc next up
we have d trace DTrace is a
cross-platform auditing mechanism that
is also available on Mac OS and until
recently it was the de-facto tracing
mechanism so in a nutshell what you do
is you talk to a DTrace driver and you
either do this through an API or through
d'être scripts which are written in the
deprogramming like library language
which is why it's called DTrace and
basically you specify to the kernel what
probes or events are of interest to you
and there's thousands of these probes
that you can turn on there's ones for
you know processes Mach traps syscall
memory notifications so on the table we
can see some of the details provide urse
and again these providers basically you
can think of them as class the
high-level classes which the probes are
kind of associated with so here's an
example of using DTrace this is actually
a dtrace script that ships with mock OS
and it's called exec snoop and what it's
designed to do is basically allow you
from user mode to observe process
creation
and exit so basically it's a process
monitor unfortunately though on recent
versions of Mac OS DTrace is neutered by
Apple's system integrity protection or
sip basically Apple says okay DTrace is
awesome but we think it's a little too
powerful for the everyday user so we are
going to disable it so even though their
OS still ships with these scripts if you
try run these scripts they're gonna fail
it's gonna say Oh system integrity
protection is on you have to turn this
off if you want this script to execute
and you can turn system integrity
protection on if you boot reboot into
the recovery mode and toggle it but
that's gonna work for example on your
own developer box if you're poking
around but if you want to utilize DTrace
for example in a security tool that's
not gonna work for end-users because
they're obviously gonna have system
integrity turned on and they're not
gonna want to jump through the hoops of
turning it off so finally we have open
DSM and open DSM as I mentioned is the
de-facto auditing mechanism on modern
versions of Mac OS interestingly it
originally was developed on Solaris and
then was ported to Mac OS by McAfee
Apple apparently had a contract with
McAfee to do that and on the slide we
can see kind of a conceptual overview of
how open bsm auditing works so in the
kernel there's going to be some
auditable event for example a new
process that's created this will get
noted by the open BSM subsystem it will
then be added to a kernel queue and then
committed to user mode either by writing
to the open BSM audit a log file or to
the user mode audit pipe so let's take a
closer look at this briefly again we
have the cisco interface that we talked
about before and in this there's also
some code to generate open BSM auditing
events so for example we can see there's
a call to audit underscore sis call
enter and then after the sis call has
occurred there's a call to audit
underscore sis call underscore exit
again these are open B SM macros in the
kernel that will generate audit events
so Jonathan's book kind of goes into the
technical details of all of this
but basically what these macros do is
they generate audit events and then
propagate that out to user mode either
by writing to the log file or to the
audit type so one of the cool things
about open BSM is you can configure
configure it with a variety of files and
what the configuration files allow you
to do is specify to the kernel what
events are of interest to you so
interestingly this is actually enabled
by default on Mac OS and if we look at
for example the audit control file which
is in /xe slash security we can see
there's these flagged parameters that
have a variety of values specifically
ello and comma AAA we can look at
another file the audit classes to kind
of decode what these are so we can see
that ello maps to login logout AAA to
authentication and authorization so what
this basically means is the kernel is
going to be auditing login and logout
events and also authentication and
authorization events but no other audit
mechanisms audit events are going to be
recorded unless you modify these flags
so for example if you want to audit file
events you basically just go in and edit
these flags
all right let's briefly talk about the
audit logs
they're basically stored in slash var
slash on it and there are several files
basically when a file max is hit what
happens is the kernel just creates a new
file and you can always tell what the
current one is because it's going to be
symlink to one that ends in knot
underscore terminated now if you dump
the data in these open BSM audit log
files you'll see that the data is in a
binary compressed proprietary format
luckily though there's utilities we can
use such as Apple's PR audit and this
will decode the data for that so if I
for example generate a login event by
executing sudo and then some user and
then when I'm done type exit to
basically exit that session if I then go
and examine the current open B SM audit
log file I can see that both the user
authentication event and a logout event
has
being recorded by the operating system
okay so that wraps up our tour of
auditing capabilities of Mac OS now the
question is you know what of these
mechanisms should we use either to
perform continual auditing perhaps for
incident response or most importantly to
me programmatically in security tools so
FS events is pretty good but the main
limitation is it can only record file IO
events so that's a pretty big limitation
if we for example want to monitor
process events or Network IO events we
can't use the FS events ApS kadiebug is
really powerful but there's one main
problem with it and that is there can
only be one consumer at a time so if you
write a security tool and you're using
the kadiebug auditing mechanism and then
the user for example wants to use FS
usage which is Apple's built-in file
monitor that ships with Mac OS FS usage
won't work anymore and we'll throw an
error message saying hey someone's
already using kata bug kata bug event so
this is not really something you want to
cause users so again it's not maybe the
ideal mechanism to use DTrace again is a
great mechanism but because it's not
compatible with system integrity
protection again it doesn't make sense
to put into a security tool that you're
going to deploy to a lot of machines so
this leaves us with open BSM which kind
of checks off all our boxes it's
compatible with system integrity
protection and gives us access to all
the events of interest it also has a
nice programmatic API and there can be
multiple consumers so now let's talk
about how to leverage open BSM
programmatically in Mac security tools
so one of my side hobbies is to create
free a lot of open source Mac security
tools and these tools need to perform
things like tracking file a file file IO
monitoring for new process creations and
a lot more you can also imagine perhaps
you want to create more traditional AV
tools or malware analysis tools for
example a file aman or a process maan
that you know can use these auditing
mechanisms so I used to use DTrace
programmatically but as I mentioned due
to system integrity protection it's
essentially dead luckily though we have
open BSN so programmatically how does
one utilize or make use of open BSM in
code for example in monitoring utility
now we'll dive into each of these steps
but conceptually from a high level it's
pretty easy
first you connect to the user mode audit
pipe you then specify what audit events
are of interest to you for example you
can say I want file events and process
notifications and then you basically
read off this pipe and the kernel will
deliver to you audit events so pretty
standard
so I mentioned step one is to connect to
the user mode open bsm audit pipe so in
code as root you just call f open on
this pipe and it's at slash dev slash
audit pipe and then as audit events are
captured they will be written out to
this pipe from kernel mode so now we've
opened this pipe we need to specify as I
mentioned what audit events are of
interest to us so here for example let's
build a simple process monitor so we're
gonna say okay we're interested only in
process events so we can go into the
audit underscore class file and look up
what open BSM audit events relate to
process creation process events and we
can see there's two there's pc and exec
so in code what we do is we basically
send an i octal to the kernel saying hey
these are the open BSM
auditing events that are are of interest
to us now we've opened the fight pipe
and configured it we can start reading
off it and since we've configured it
anytime now there's a process event the
kernel will deliver that to this pipe
and we can consume off that so if you
look for the documentation you can see
there is a open BSM api called au
underscore read rec for record and it
basically takes in the file descriptor
to the audit pipe and a buffer for the
record
now the documentation says it
terns zero on success but that is not
true it actually returns the number of
bytes it is read so the documentation is
incorrect so now we have an audit record
that we have read off the audit pipe and
Apple calls this a token record we have
to parse this in order to consume it or
utilize it in our tool so what we do is
we invoke the a you fetch tok method to
tokenize the audit record and this will
split it into a variety of tok ster
structures now each of these structures
contains some important members the
first is the ID or type this allows us
to identify the type of structure it is
and all these structures are listed in
the lib be smh file which ships with mac
OS so some notable token types include a
header and a trailer which obviously
start and end or record and then
there'll be other token types that
correspond to the event so for example
for a process creation event there will
be a record that corresponds to the path
of the process that is created there
will be another one for the process
arguments process parents etc etc so
what we do is to process these tokens we
just switch on the token type again to
determine the type of token that we have
and then we have tokens specific logic
to pull out the information that's of
interest so for example I mentioned
there's going to be a path so what we
can do is when we see the token that's
associated with the path we can record
this path for example convert it into an
nsstring object and then consume that in
our tool so if we put this all together
we now have a nice process monitoring
library this library is open source
available on github and it's called proc
info the cool thing about it is it's
very easy to use you basically link in
the library and then what you do is you
create a block of code that you want the
library to invoke anytime there's either
a process creation or process
termination event and then you basically
allocate a process monitor object and
then invoke the start method passing in
the block the library takes care of
everything else
all the auditing
figuration the tracking of process
events parsing all the tokens etc etc
and then it'll invoke this block of code
whenever there's a process event and it
also does other cool things like
generate the signing information of the
process that's being created extracts
the ancestors etc etc so very easily now
whenever a new process is created you
can see who created it and also the
signing information so you can say oh
this is a trusted apple process this is
something from the Mac App Store or this
is unsigned that's odd okay so that was
an overview of auditing mechanisms and
how to utilize open BSM programmatically
in security tools now since this is kind
of a technical hacker conference let's
now talk about some more interesting at
least to me topics so time to put on our
hacker hats either gray white or black
you know we're not gonna discriminate
here and we'll talk about some kernel
bugs that existed in Apple's open BSM
kernel mode code so the first bug we're
gonna talk about is a kernel panic and I
kind of like this bug because I found it
totally by accident and I always kind of
have this joke that like finding bugs on
Mac OS is so easy that like if you're
writing security tools or just Splunk
around like you're gonna inadvertently
come across a lot of really interesting
bugs so I had this process info library
I'd written again it utilized the open
BSM auditing subsystem to generate
process events again I mentioned that I
have a variety of security tools for
example one that generically detects
ransomware and one of the capabilities
of this tool is it needs to track
processes so that when a certain process
create creates files it knows you know
what process that is who spawned it etc
etc to basically classify that process
so I swapped in my proc info open DSM
auditing process monitoring library ran
the tool went off to lunch and a few
hours later came back and my box had
panicked I was like okay it's kind of
annoying like maybe there's some faulty
hardware but started the tool again and
came back the next morning again my box
had panicked
and again first I was a little annoyed
but I said oh hey now we have a
repeatable Colonel panic on the most
recent version of Mac OS like that's
kind of cool so let's do now is walk
through that kernel panic to find out
the underlying cause of the bug so the
first thing we're gonna do is we're
gonna start with the kernel panic report
and kernel panic reports are great
because as we'll see they have all the
information that you need generally
speaking to track down the underlying
cause of the bug so if we look at this
there's a lot of information but I've
highlighted in green kind of the pieces
of information that are valuable to us
so first we see there's something that
says type 14 equals page fault this
indicates why the kernel panic it's
basically said there's a page fault
which means there was an invalid read or
write likely to an unmapped page next we
have our IP which is the 64 bit
instruction pointer and this has the
address of the faulting instruction so
this is the line of code or the address
of the opcodes that were being executed
when the kernel panic occurred finally
we have fault CR 2 this has the actual
address that the kernel was trying to
reference that triggered the page fault
and then the very bottom we have the
kernel slide which is just the amount in
memory the kernel was slid due to
address space layout randomization so as
I mentioned the goal is to figure out
why this panic occurred so since we have
the address of the faulting instruction
from the kernel panic report what we can
do is we can disassemble the kernel and
go to that address in the disassembly so
we load up the kernel in Ida Pro and the
first thing we have to do is we have to
rebase the file image so that it Maps
the in memory memory image because again
when the kernel is loaded it gets slid
in memory because of kaal arm so once we
rebase the kernel we have the address
from our IP in the kernel panic report
we put that in the jump to address pop
up in Ida and we hit G and what we do is
we land
a compare instruction in the audit argh
sock adder function this is an open BSM
audit function which makes sense because
again my utility user mode utility that
triggered the kernel panic was utilizing
the open BSM auditing so basically this
now indicates that in user mode if you
were talking to the api's there was some
bug in the kernel that would trigger and
crash the box and we can see it's a
compare instruction that's doing a
compare of our bx + r 13 + 2 and it's
basically checking if that address is 0
now luckily the audit Arg sock adder
function which we'll be talking about a
lot is open source so we can browse to
open source Apple comm and look at the
source code for us so the goal is to
figure out what line in this source code
maps to the compare instruction again
the compare instruction we got from
disassembling the kernel so if we look
at the kernel code we can see that when
bind is called on a socket it invokes
the argh audit argh macro to audit the
socket event basically says okay binding
a socket is an event that might have
security implications so I'm going to
audit this event so in turn it calls
this audit argh
sock adder function which among other
things determines what the type of
socket is creating so we can see there's
a case for unix sockets AF underscore
unix and what we can see is at the
bottom of the slide there is some code
that's checking to make sure that the
path of the UNIX socket is null
terminated so if we look at the source
code we can see that this basically maps
to our compare instruction so the
question is you know what are these
register values and more importantly why
does this comparison cause a kernel
panic so if we look closer at the audit
argh sock adder function we can see it
locally declares a sock adder UNIX
structure for a UNIX socket and if we
look at the definition of this structure
it's in the U n dot H file we can see
that there's a length a family and then
so if we go back to the code for these
UNIX socket we can see that it basically
assigns a pass in passed in sock adder
structure to the UNIX sock addict
structure and then calculates a length
now if we go back to the compare
instruction we can now understand the
values of each of these arguments so for
example the RBX register at the time of
the crash is a pointer to the UNIX sock
adder structure r-13 is the length minus
two and then there's a plus 2 because
the offset of the path starts at plus 2
within the socket structure so since the
kernel panic report contains all the
register values at the time of the crash
we can basically plug in the values and
basically recompute the address it was
doing the compare instruction so we
basically go to the crash report pull
out our BX our 13 and add 2 and what we
do is when we compute that address we
get something that ends in 4 F 0 0 0 and
two observations about that first that
matches the fault CR to address which
indicates yes this was the address that
caused the kernel to panic and also
since it ends in 0 0 0 this indicates
it's at the very start of a new page so
here's a diagram of exactly what was
happening to cause the kernel panic so
basically we have this UNIX structure
that was size 16 or 10 in hex it was
allocated at the very end of a memory
page so basically memory page the last
thing it had was this UNIX strong UNIX
socket structure what happened was the
compare instruction came along and since
it's trying to check if the path in the
UNIX socket is null terminated it goes
to what it thinks is the end of that
structure but it actually goes one byte
past that and tries to read that byte
and since the very next byte after the
path is an unmapped page in kernel
memory when the instruction tries to
access that that's obviously going to
cause kernel
so I was intrigued I was like okay I
understand
you know why this bug is occurring but
like you know why is this wise there's
this off by one reader so if you read a
little more about UNIX sockets you find
out that this path does not have to be
null terminated which is why Apple is
checking to see if it is null terminated
but there's all this confusion online
about like how to check this path and
the funniest is if you actually look at
the source code in the Linux kernel they
have an intentional off-by-one where
they actually go one byte past the end
of the path and check if that is a zero
there however the code the comments in
the code say this is intentional and
this is okay because we guarantee that
the very next byte after the end of the
path is always going to be mapped in so
this is never going to panic the box
however that same assumption does not
hold true on Mac OS so when you get a
structure that's allocated at the very
end of a page with the adjacent page
being unmapped this cause as a kernel
panic so kind of an interesting bug
alright so that was a kernel panic kind
of lame I mean it crashes the box it's
just a read it's not exploitable so
let's talk about some real kernel bugs
now so the first thing did I reported
this bug to Apple I said hey guys you
know here's the scenario where user mode
code can trigger a kernel panic if a
UNIX socket is being audited and the
structure happens to align right with
the end of an unmapped page and they
said okay cool we'll fix that they
silently patched it so there's no CVE
associated with this but if we look at
the patch we can see that the way they
decided to fix this was by using aster l
copy now as their comment notes they say
make sure the path is null terminated
and if you're familiar with ster L copy
it's basically a safe ster copy which
means it'll never overflow the buffer
but it will keep copying until it finds
a null termination but again this path
is not necessarily null terminated so
more specifically ster all copy is as I
mentioned going to copy until
it fills up the buffer or until it hits
a null or zero so if our socket is
smaller than the buffer and we create a
socket that isn't null-terminated we can
potentially leak random kernel memory
data so let's take a closer look at this
first we have some code that creates a
UNIX socket and if we look at the kernel
we see that this is going to call first
when we call bind on this it's going to
call something that's a method or
function called get soccer sorry get
sock adders underscore s and what this
function does is it's going to zero out
a structure and then it's going to copy
in that soccer socket structure that
we're trying to Aude it basically it's
copying it in from user mode to kernel
book and it copies this in via the copy
in method which just copies in some
specified number of bytes so now let's
try to create a UNIX socket that is not
null terminated because again we want to
basically get the vulnerable ster L copy
to be called on a string that's not mall
terminated so then it starts copying a
random kernel memory into user mode so
as I mentioned the way they copy in the
path is they first zero out the
structure and then copy that in so since
they zero out the structure we have to
create a path that fully fills up that
structure because otherwise it'll be
inadvertently null terminated because
they first zero out that structure so if
we look at the size of this structure we
can see it has a max size of 128 so what
we do in user mode is we simply simply
allocate 128 bytes we fill that with 41
41 41 and then we basically set the
length to max and the family to UNIX
socket we then call bind which will
trigger the audit event of the socket
and what we can do is we can see we have
the socket structure on the slide so
again we can see it's 128 bytes
it's a UNIX socket and it's filled with
40 ones most important thing though is
it's not null terminated so there's no
zeros in this structure if we then call
bind this is going to trigger the
vulnerable ster l copy in kernel
and what its gonna do now it's going to
start copying bytes from our non
null-terminated path so here's a diagram
of that and we can see if we have the
structure in memory if after the
structure there's a one two three four
five six some number of bytes the stur l
copy is just going to start copying all
those bytes and then write that out to
user mode either to the log audit log
file or to the audit pipe and again
obviously if there's sensitive
information in the kernel hashes tokens
and etc etc this will all get leaked
I think end this was apple's fix to a
camp kernel panic report so that's kind
of the funniest thing of this all so
let's briefly walk through this in a
debugger to show this kind of happening
in action so the first thing we do is we
set a conditional breakpoint on bind and
then here's our user mode code to create
this null non terminated UNIX socket we
then call bind in user mode this will
trigger our kernel mode breakpoint to be
hit and then if we dump various values
we can see okay yes this is our kernel
this is our UNIX socket and yes it has a
path that's not null terminated so if we
then set a breakpoint on the vulnerable
code we can hit continue in the debugger
and then it'll break as it's about to
audit this UNIX socket so at that point
we can look at the registers and we have
a table on the slide which is the
mapping of what the registers contain at
the vulnerable stur L copy for example
we can see that our ax points to the
index of the bite to copy our BX plus
two is the source sort bytes which is
the pass and then our BP minus 130 is
the buffer it's going to copy it into so
if we step over this we can see that it
returns 127 which means it's copied 127
bytes so why 127 so recall we're copying
from a UNIX sock adder structure and
we've set its size to 128 now the path
starts at offset 2 which means that the
maximum path length is 126
in memory if we dump the path there that
we're about to audit we can see that
right after it there's a random d7 and
then a random 0-0 so what happens is the
code has gone through copied to the end
of the path since the path isn't null
terminated it then copied the next byte
which happened to be a random d7 looked
at the next byte that happened to be
zero so stop copying so in this case
we've leaked one byte now you probably
want to leak more than one byte at a
time and it turns out you can so if you
create a socket that's bigger than 128
instead of getting allocated on the
kernel stack it gets allocated on the
kernel heap so then you create this
socket and again just call bind on it
and the vulnerable ster I'll copy we'll
just start copying a random kernel bytes
until it hits a zero so you can change
the size of the socket you can call this
as many times there's no side effect of
this but every time you do this you will
leak more and more kernel memory into
user mode okay so we've talked about
kernel panic and a kernel information
leak but I still wanted something a
little better so if we look within the
same audit argh sock adder function we
can see that there is an interesting B
copy and a B copy is just a mem copy
it's basically copying something from a
source buffer to a destination buffer
and some number of bytes now anytime you
see a B copy function if it uses the
source buffer as the number of bytes to
copy take a very close look at that
because if the destination buffer is
smaller than the source buffer you may
get a heap overflow so what B copy is
doing it's basically just copying a
soccer a socket into a sock adder
structure so if we look at the table on
the slide these are exactly what it's
copying so the source is just a sock
adder structure the destination is a
sock adder storage which we'll look at
that closer and the size is the length
of the source buffer so the question
then comes is can we basically create a
source sock
socket sock adder structure that's
bigger than this destination buffer and
the answer is yeah so the destination
buffer is always going to be a hundred
and twenty eight bytes in size so if we
can create a socket that has more than
128 bytes we will get a nice ring zero
heap overflow so again we're gonna use a
UNIX socket because a UNIX socket allows
you to specify a path and the path can
be bigger than 128 so this allows us to
create a socket that's essentially
bigger than the destination buffer so we
create the socket and then we call bind
the call to bind will trigger the
vulnerable audit code which is trying to
audit the socket and then this will
invoke the vulnerable B copy so the
diagram on the slide we can see we have
this UNIX socket I've created it to be
200 bytes in size it could be bigger
could be smaller but the important thing
is it's bigger than 128 so the B copy
comes along and says okay I want to make
a copy of this path I want to make a
copy of this socket structure I'm going
to basically copy it into this
destination buffer that's 128 bytes in
size and the length I'm gonna use is the
size of this source buffer not the size
of the destination so since the source
buffer is bigger than the destination
buffer we get an ICP overflow so how do
you exploit this vulnerability due to
time constraints can't really go into
all the details but it's actually pretty
easy for a variety of reasons so first
we control the number of bytes to copy
so it's a tactical over overflow you can
copy and overflow as many or as few
bytes as you want we also control the
values of the bytes being copied so they
can have zeros they can have 7f they can
have you know there's no constraints on
that most importantly though if we look
at where this dish destination buffer is
that's getting overflowed we can see
that it's part of a larger structure so
it's self-contained with something
within another structure and this is
important because this means that after
that buffer there are always going to be
other values for example pointers that
we can corrupt so normally when you're
exploiting a heap overflow you don't
know what's going to be next to the
buffer you're overflowing so what you
have to do is you have to spray you have
to allocate you have to groom the
Colonel Heep then you have to try to get
an adjacent object that you control
trigger the overflow and then gain code
execution that way in this case though
we have a self-contained overflow and
again the destination buffer is part of
another structure so there's pointers
there that we can tactically hit we
always know those pointers are going to
be there so here for example we can
corrupt some of those pointers and set
them to 41 41 41 41 so once you have
this ability there's some other talks
that have been presented about exactly
how to leverage this to get control of
the instruction pointer and then do all
sorts of evil things for example
disabling system integrity protection
gaining unsigned code execution in the
context of the kernel all that good
stuff all right so let's wrap this all
up so we started by talking about the
many benefits of auditing so again if
you're interested in doing malware
analysis or writing security tools for
mac OS definitely check out the auditing
mechanisms you can utilize them to
create very powerful auditing tools
pretty easily we talked about a kernel
panic that was inadvertently found by a
user mode process monitoring library
that was silently patched in the 10.12
dot 4 dot beta when I looked at apples
patch I saw that not only had they not
patched the bug they actually had
introduced an even worse vulnerability
so a little secret look at apples
patches because they mess them up all
the time so you can find some really
interesting bugs basically just wait
till they release some CVE details diff
the kernel will look at their patches
and Frio days and finally we also showed
a heap overflow that would give us code
execution in the context of the kernel
allowing us to do things like bypass
system integrity protection or execute
unsigned code in the context of the
kernel so very briefly since you're
attending my talk on Mac security I just
want to briefly mention my personal Mac
security website a lot of free
open-source Mac security tools I also
blog about Mac malware
and blog about zero days and
vulnerabilities I find so everything
here is free so hope this doesn't sound
like a sales pitch alright so that's a
wrap again I'm on Twitter a Patrick
world all the website is objective-c and
I think we have a few minutes for
questions if not I will be around after
the talk I would love to chat again
thank you so much for attending my talk
I really appreciate yes question yes so
the question was was the heap overflow
related to the same control flow the
same auditing mechanisms and the answer
is yes so all three bugs I talked about
were all within the open BSM code which
lives in the kernel the auditing code
and actually all three bugs were in the
same function so there's a lot of other
auditing functions that you might want
to take a look at I don't think anyone's
audited the audit code but again yes so
basically to answer your question it you
know it was all within the auditing
subsystem first the the the panic was
triggered inadvertently when I just
started using it and then I took a
closer look audited some of the code and
found the kernel information leak due to
apples patch and then the heap overflow
was just actually three lines of code
above so I would audit that code there
might be some other interesting bugs
there yes question so the first one was
okay so the first one the first panic
and I was like this is annoying I was
like oh cool this is like a security bug
and then I decided to look at apples fix
because I wanted to make sure that when
I deployed my tool my user mode tool it
wasn't gonna cause users computers to
panic and then I looked at their fix and
I was like what were they thinking like
they they say it's not null terminated
and they use asteroid copy and then you
know the the function was 20 lines of
code and I was okay there's very two
bugs in here there might be something
else and you know when I was testing the
kernel information leak it actually
triggered the heap overflow so again
like finding kernel bugs and
you know it's it's still pretty easy so
or maybe I'm just really lucky but now
it's it's easy awesome well thanks again
for attending and I'll be around if you
want to chat also these slides I will be
online I think tomorrow so thanks again