all right it seems like it's working
and let me just message in the discord
to make sure everyone knows
that this is happening
all right seems to be working
all right what are the uh current
questions for toddler two
let's see how uh it's going i know it
had a little bit of a
slow start but i think once people
get through level one and like maybe
level two as well
that the remaining levels will be pretty
uh it'll be easier i think
i think the biggest hurdle will be
getting through level one
so i think the
um so the question was basically should
we just copy and paste the functions
that yawn wrote
um in the the q a
so the functions that he wrote are
definitely extremely useful
um for showing
how you can basically abuse both the
race condition as well as the heap
corruption issue and combine them
together to start getting arbitrary
reads and then at the end he kind of
also showed arbitrary rights
um i wouldn't
completely recommend just like outright
copying it
um i think to some extent copying it
though
and kind of
looking it over and making sure that you
actually understand what it's doing
would be a very good idea um i think if
you just
outright copy it you'll probably get
stuck and
you since you just copied the code you
won't understand what's going on
why it's broken um
[Music]
so yeah i would if you're feeling very
stuck on level one
hopefully i can address that as well in
this these office hours
um but his code that he has there is
very
useful but i would use it as a
i would make sure that you don't just
outright copy it and that you
work on understanding it otherwise you
might get stuck and that's not good
yeah like understand yeah exactly so
and maybe maybe what i'll do is actually
take his code and just do another
like walk through of why it works
maybe that would be the best way to go
um i don't know if i have a good way to
copy it but i guess
i mean i can just pull it up in my
browser on the side
and then just like transfer it over
and then we can go through it yeah i'll
actually do that
um that seems like a good idea
um okay so let me
start by launching the challenge in
testing mode actually one second
someone was trying to call me let me
just make sure that they
uh know that i can't call them for an
hour or two
okay
um it's so i don't have the issue same
issue as jan where he was like on a
laptop without enough
stuff going on the issue for me
um is that basically i only have one
big monitor and the way that i have
everything laid out
i think for zoom to work i need to have
basically
a projected window where it's like kind
of always displaying what's live but as
soon as i switch away from that it's no
longer
projecting and then it just won't work
so i haven't had enough time to
investigate how to make that work so
yeah for now unfortunately i can't
screen share on zoom
um okay so
let's actually did i don't know if i
actually started the challenge
let me start level one in practice
there we go
okay so
um ctf we'll just make their
toddler too and i will start
by um
just to speed things along since we've
already seen young go through and
write his code for basically getting an
arbitrary pointer
and his code for um
getting an arbitrary read using that
arbitrary pointer i am just going to
um copy from it and then we will
go through and explain basically line by
line
what's going on there okay so let's
start
by let me think of how to copy this
yeah we'll just do it this way
okay
actually let me also import tone
i don't know why he does this insane
like os kill
but for now we will roll with it i'm
pretty sure you can just call
os dot underscore exit like a sane
person
maybe i am missing something so we will
for now leave it
let you see
almost there
hmm that doesn't look great there we go
oops
okay and then
clean and then we need to
get the arbitrary right
one second
just trying to skip around in this video
to uh just copy it out so we can just
work off of the same code
and then explain it um
okay and then so there
is arbitrary read yeah okay
arbitrary read which takes r1 r2 r3
and the address that you want to read
from
and it calls controlled allocation
r1 r2 r3 address
and then we
scanf over it okay
oh not yeah so to
explain it after
i think that's the end but let me just
double check here
and then return link yep okay
so that is what he created during the
extended q a
um so the first thing i'm going to do is
let's just
run it real quick to make sure that it
works
and then i will go through and explain
line by line
what's going on
okay so
let's create our process
as process
and then oops
and then we can do um we want our
three connections so the exploit that he
demoed is working basically with three
concurrent connections to the program
so we can do um let's go ahead and say
r1 equals pawn dot remote
vocal host oops
one two three seven we want three of
these
okay it looks like this will already
clean them for us
and then what we just want to do an
arbitrary read
i guess um r1 r2 r3
um we need to figure out actually where
we want to
read from so in level um
how do i show this let's show we
launched toddler two
and then we netcat localhost 1337.
actually i guess it told us in the uh oh
i'm in
testing in the teaching one it'll tell
you basically that
the the secret is stored
in the bss so
basically the way it works is that we
want to ultimately call this send flag
function because this will give us the
flag
but it asks us for the secret before it
will actually give it to us
and if we give it the wrong one it says
not authorized give it the right one
it'll say we're authorized and print out
the flag to us
we have the ability to do this malek
this free this scanf and this printf
which i will get further in
in a little bit here for explaining
exactly what's going on
okay so
let me close that
close that
um okay so the question or the first
thing that we need to
figure out is where
um where in the bss we're storing it to
so actually something else to note
is that with level one um
what oh that's right check sec for some
reason
makes that impossible okay so something
to note for level one and level one only
is that pie is disabled i mean since
we're just
since we're storing it in the bss it's
just going to be at a basically a
constant address we don't have to really
um
leak something and then do an offset of
that leak or something like that it's
just
always going to be where it's going to
be and we need to figure out where that
is so
if we go ahead and
do this and then we want to jump to main
because that's where it's going to
ultimately
load it up actually i know for a fact
it's going to call load secret at some
point
um okay and it tells us here
that secret is um at this address here
so this is where the secret is going to
be stored
um there's going to be
16 bytes of secret as it turns out our
leak only allows
us to leak eight bytes at a time but you
could either
it turns out you could actually leak it
backwards and that would work
or that you can just kind of go through
and run it all twice at the
two different offsets since um the
secret doesn't change it's kind of
constant for whatever your flag is
okay so let's go
back then and go into emacs
let's go ahead and just say
secret adder equals
that okay and that's exactly what we
want to leak so for now let's just leak
the first eight bytes and then we can
look into
speaking more if this uh works
um okay so
in theory if i copied everything
straight out of his code this will
actually just immediately tell us the
secret or he might have to run it a few
times because of the race condition but
we will talk about that more oh and
we'll also have to
import some things uh i think it's
probably actually just os
okay
um okay
reference before assignment okay
actually i forgot to see what line that
was that was on line 42.
um okay let's just go ahead and do
global idx
actually do we have it set up to be
printing things
um did i skip over that part let me see
one second
oops
yeah whatever we'll just add it in
ourselves okay so let's go ahead
and
um once we're out of this loop
let's just print allocation
loop done or something just to tell us
we're making progress in our
in our exploit and then let's also just
um just print what we're trying to
point allocation at pointing allocation
at
hex address
okay
and then let's run that
allocation loop done
oh we're not like printing anything are
we but why would it not exit hold on
let's see here
so there's definitely no loops that are
gonna happen after this but i guess we
could be getting
hung on something let's just call this
leak and say print
leak leak
and i think this is going to return
an integer to us so for now let's just
um
let's just call hex on it and
yeah let's see
actually is this message yeah i think
that's right
okay let's see
so we're getting stuck on something so
we're getting stuck maybe on this read
until message
colon blah okay
um so we sent
this this okay hold on let me
see something real quick
okay let's see
what is coming back just quickly looking
to see
if anything doesn't make sense actually
you know what yawn at some point i
remember
swapped this let's just go with that let
me see
what it was that he swapped i remember
he split that apart
to happen from two different things
let me see if i can find that
hold on
or let's just yolo it let's see if this
works
i think this is what he did
okay
okay so we're still getting stuck let me
um turn
actually that'll be hard to do there i
guess we could do it after this loop
so after this loop we can do
[Music]
um wait a second
we're getting through this loop
where are we getting stuck on
hold on yeah we'll do it anyways context
log level equals the bug
which will make pencils basically just
start reporting everything going on to
us
um okay
so we sent this we sent this
okay
um and then
it's called the mouth called the free
called
send a line of the address
oh but we never called like a printf or
something
there's no way this logic makes sense
did i like
copy from his code wrong hold on let me
see what's missing there so the issue is
that we're calling scanf but we're never
calling printf and it's printf that
actually tells us like message colon
whatever
hold on
okay i think i was starting to copy his
arbitrary right this makes way more
sense
yeah this this logic doesn't make any
sense so
as you can see like we're already like
trying to overwrite data right but in
theory
based off of the name of this certainly
right we've already controlled our
allocation
to give us basically um
to have basically malicked already at
this address we can see that the very
last thing we do is call malik here so
in theory this should already be
pointing at
address um so this scanf doesn't really
make sense
so if we do instead um printf
and like sending data this is like
getting ready to do an arbitrary right
so let's see if this works um
yeah this like sounds way more sane
um and that does not work because
we seem to have forgotten an f
uh yeah we don't want to be we want an f
oh we can already see though in our
history that it was working okay
um so in this case it failed
realistically the
same option would be to like see if it
failed and just kind of rerun it if it
failed
and maybe i'll add in support for that
rather than just like having to rerun it
yourself
because we can already detect like hey
we didn't leak it correctly so something
went wrong okay and here we can see
it's more readable actually in this uh
debug message that we are able to do
a leak okay so as i said before though
it's not really uh all that exciting to
just go through and copy yon's code and
just like
go from there something that's kind of
lame
and maybe more importantly like you're
probably not going to learn just
outright copying it
and you very likely could get stuck
because you don't understand what this
copied code is doing it's uh
it's no good the whole point of this
class is to learn let's not just copy
code
okay so what is going on in all of this
code
so maybe it would make more sense if i
start by um if i start by kind of
describing what our problem is
and you would discover this doing
reversing but for brevity's sake let me
just kind of tell you what's going on
it's
basically the same thing as what yawn
showed in his q a
in terms of how this challenge problem
is set up so
if i let's just create something
we'll just call it challenge or whatever
who cares okay so how does the challenge
work so we have
a few operations um
trying to think how can i easily show
ah whatever we'll just write out what
they are so we know we have the ability
to do malik
we know that we have the ability to do
free we have printf we have scanf and we
have sent flag these are our
operations that we get to do so the way
that they work
you've already seen kind of in
in baby heap maybe kind of how this
works some extent
is that we're specifying an index when
we call malik we'll also note that
unlike baby heap we're not specifying a
size we don't get to
specify um how big of a
thing that we're going to malek but
turns out for our purposes in exploiting
that doesn't really matter all that
matters is that it's small enough and
it's going to end up in t
cash um we don't care about
controlling the size per se we just want
to corrupt it
into allowing us to malek basically to
an arbitrary address
okay so how does this work we have
basically 16
allocations just sitting in global data
accessible to all threads
we also have basically 16 booleans
like is allocated or something
that's kind of how you could think about
that
so how malik is going to work is it it's
going to check
first to see are we already allocated so
like
it'll be i'm just going to write it in
like python ish pseudo code
so if um not is allocated
then we will just call like malik
1024 um and we're going to do like
allocations index equals that
uh actually and then also we have to
specify index so this is the
basic gist of the logic for how malik
works
it checks to see if um and we can
basically assume that all of these start
out to like
false false false false whatever or
maybe we'll stick to
pythonish notation whatever
good enough um and maybe these just
start out as like
null null null
blah blah blah okay so this is how it's
all initialized too
um because it's in the bss which
basically means it's going to be zero
initialized and these are all like the
zero values for their types
okay so what does malik do malek checks
are we already allocated and if we're
already allocated we don't want to call
malik because
if we did that then it would be like a
um it'd be like a memory leak right we
would have
mallocked over something where we
already so like
right here would be um say it's like the
second thing
this might be like one two three four as
what malek returned or whatever and this
would be like true
um we wouldn't want to allocate again
because then we would overwrite this one
two three four
and it would become like one two five
six but that pointer to one two three
four would have just suddenly vanished
um we'd no longer have like a reference
to it and be a memory leak so that's
kind of like conceptually why a program
might want to do this
um we wanna like basically keep track of
what's allocated
and not have memory leaks basically
um okay so i'll just go back to normal
um so this is kind of maybe a fairly
common pattern
that if you have a bunch of allocations
and you want to like start
maybe randomly storing data the user's
in it but
i don't know you could kind of think of
how a program might be written in this
way
okay so what does free do it does kind
of
the opposite check it checks if
something is allocated
so if is allocated index and then if it
is allocated it'll call
free allocations index
okay this makes sense because we don't
want to call free on like null or
something or something that isn't
allocated
um we only want to free it if it is oh
and actually something to point out here
i guess i missed it is that is allocated
index
now equals true and is allocated
index equals false so it's basically
just like a
a single bit state of this allocation
basically checking
is it allocated or is it freed right now
and only allowing us to do
um kind of the opposite operation
and then also these we only want to do
them if something's allocated
so we'll say like if is allocated
actually is that what this is doing i'm
pretty sure we would do that
but maybe we don't check that hold on
let me
let me cheat and look at uh the program
um
maybe we don't do that maybe this is yet
again another
bug that we introduce into the challenge
um
oh no we do that right that's what
causes it to say like message none
and yeah okay so this is what happens
here but we don't exactly check this is
what we do though
um so i guess we can keep it in this
notation so if it is allocated what
we're going to do
is we're going to printf message
um and then like
allocations index right so whatever the
data is that's stored
in this program we'll just kind of print
it out and then
otherwise we'll just print
um printf
message none or whatever
um so that's kind of the logic of printf
and scanf is similar so something else
to pay attention to is on the stack
on the stack there's like an input
buffer
and the input buffer is basically when
you
type in malik we're calling scanf to
this input buffer and then we compare to
see if the input buffer is malloc
or if it's free or whatever it is so
that actually also
exists it's not super relevant but it's
kind of relevant in the case of scanf's
logic
which does if um is allocated
index we will go ahead and call
uh scanf to allocate
allocations index so this allows you to
like basically put data over that
allocation
and otherwise it turns out we actually
just call scanf
on input buffer but this doesn't
really matter there's not really an
exploit here
per se at least i don't think there is
um either way it doesn't really matter
for our purposes
does anyone have any questions over how
this
program is working in terms of just like
the challenge program itself
it's kind of important to understand how
the challenge works
before you start exploiting it and then
of course this basically like
ask for secret if secret
correct out flag
and um i guess something different than
the
the heap challenges you can't actually
overwrite the secret and
make that be like your attack plan um
when we go to check if the secret is
correct we basically regenerate the
secret on the fly and compare with that
so even though we're storing the secret
in the bss we're not actually comparing
with that
um we're just like generously
leaking the secret into the bss
overwriting it's not going to allow you
to win you have to
read it just kind of something to point
out it's not too big of
a deal you might have gotten stuck on
that so it's important to know that
the exploit's basically going to look
the same um
for most purposes um okay so
this is the logic i don't see anyone
asking any questions about
how the challenge works so i'm going to
assume that kind of makes sense it's
pretty similar to
baby heap with maybe some minor
differences basically the main
difference being this uh
is allocated um
uh that we're maintaining whether or not
we've allocated so if we were to just do
this single threaded and try and exploit
this
um we wouldn't be able to do like malik
so we would be able to call malik and
then we would be able to call free
but then we wouldn't be able to do scanf
over this freed buffer
because it checks if we're allocated
in order to allow us to actually
overwrite this now free
data it would actually just scan up into
the input buffer
and this is where basically most of the
baby heap levels the
logic behind why that exploit works
would no longer work
because we actually track if something
is allocated
however this is not yeah there's a
question go for it
yeah the challenge we'll just call malik
1024 i think it's 10 25 i'm not 100 sure
on that i think the
input buffer here is 1024 also
and i think all of these like scanf
percent s's are like percent
1024s so i don't know it's it's just
specific to the challenge it doesn't
really matter
except that this means it's gonna go
into
uh t cash that's like right on the
threshold that it's
still able to go into t cash if you want
a little bit bigger
um it would no longer go to t cash and
things would get
probably more difficult um but yeah it
just happens to call 1024 you
so unlike the heap challenges you don't
specify the size
but that doesn't actually matter for um
just trying to get an arbitrary read
arbitrary right
um it doesn't really matter that it's a
10 24
okay any other questions on oh okay so
there's a
question in twitch chat so the racing
yawn talked about in the last lecture
has to do with erasing the
if statements correct exactly so in
whereas in baby heap
we don't have these is allocated checks
um
and we just kind of make it more
vulnerable or whatever but it's single
threaded so that's kind of makes sense
why you need that
this is now multi-threaded but does have
the checks so in just using one thread
one connection to the program you're not
actually going to be able to exploit
this but using two connections to the
program
since these allocations and is allocated
are just global data shared across all
the threads
whereas something like this input buffer
for instance is living on the thread
stack so it's kind of
specific to each thread i'm not that
really matters but something to
kind of note
the way that you exploit this is doing
both a heap
metadata corruption basically corrupting
the forward pointer
um and in order to do that you need to
race it so the way that you would race
it
if we think about um
kind of what we're going for so what we
really want to do
is we want to scan f
over so we want to scanf
some freed allocation
right this is how we do it in baby heap
so this is our
let's say our exploit logic at a high
level
is what we really want to do is we want
to call scanf
on some freed allocation because it's
freed it's now sitting in t
cash so if we think about some
freed allocation the way that t cash is
currently going to look
if we have let's say some freed
allocation
t cash is going to be a linked list
where we have some freed allocation
pointing to um
let's just say first eight bytes inside
some freed allocation rate
uh freed allocation this is how the
linked list structure of t cash works
right we just kind of store the next
pointer the forward pointer
as the first eight bytes inside of our
freed allocation
so if we were to go on to call malik
it would give us oops
it would give us let's call we would get
this
and then tcash would be updated to be
this and then if we called malik again
we would get this
and of course if we were able to call
scanf on some freed allocation
basically we are controlling controlling
the first eight
bytes or however many but more
importantly the first eight bytes
which means that we are controlling
the result of second malik
and as we said um this is allocated
check
prevents us from doing that all in just
one thread
because if it's no longer allocated as
in basically if it's in the t cache
already and we're like able to track
that
then we're not actually going to call
scanf on our freed allocation we're just
going to call scanf
on the input buffer and you can
basically think of that as just kind of
discarding your input
okay so in order for our exploit logic
to work
let me see how this looks uh
it's good enough okay um
let me just just kind of go crazy here
hey good enough okay so in order for
our exploit logic to work we need to
abuse the fact that we're multi-threaded
and operating on this global data
and we're operating on this global data
without semaphores which is kind of the
solution to
race conditions but the thing to note is
that
semaphores kind of require the
programmer
to introduce these semaphores you're
kind of it's
it's not something that we can just
introduce generic security mitigations
to fix um
if you don't use semaphores you don't
use semaphores or if you use them
incorrectly use them incorrectly
there's not like we can't just like
introduce like aslr and that just like
makes the exploit a lot harder or
whatever like these generic mitigations
um yeah so
i mean i guess there is a generic
mitigation actually coming up that will
be
that's in actually the latest lib c that
breaks kind of how this uh
this forward pointer logic works but
we're going to say we're on ubuntu 2004
and we're just going to use their libsy
and ubuntu 2004 is the latest
long-term release of ubuntu and good
enough it's uh
still a very valid target okay so
anyways getting back to um
translating our exploit logic maybe a
little bit deeper into how it needs to
work
so the way that this exploit logic needs
to work
is that we need to interleave these
malloc free
and send flat or then this scanf
operation
um to some extent so what we want to do
um if we just copy
malik and free
um and let's just say that this is
thread one and this is thread two so
let's just assume we have one thread
calling malik and one thread calling
free
so um and then we have our global data
which is like
is allocated
for now let's just say we're working on
let's say we're working on like index
equals zero for both of them
we'll just say that okay let's say
initially it is
set to false okay so
how do we interleave these operations or
more importantly is
is it possible to interleave these
operations in a way that it breaks
the thing that's securing the program
that's kind of what we want to think
about
in terms of these timelines so we'll
just think about it at
interleaving these operations at these
super high levels
in terms of like let's just pretend that
free is atomic it's just like
one operation that's bundled together
that is not actually the case
in theory you could be racing partway
into free because
basically every instruction that frees
to call and free might call hundreds of
instructions
you might be able to interleave
somewhere in there where the race
condition is
but let's just pretend free is um
just this atomic operation that all of
these these three lines are basically
atomic operations even though that's not
exactly true
maybe the first step is to see even if
this high level
logic can be raised without having to
worry about like at an instruction level
if it can be erased
okay so is there some sequence so i
guess the way you might think about this
is let's just assume that we have our
thread one and our thread two
and they are executing is there some
sequence of like let's pretend that we
get to control
which thread we want to step next so
only let's pretend only one thread is
going to step at a time and we get to
choose which one
maybe that's how you can think about
race conditions in order to see if there
is a race condition
so we know that at some points
yeah okay so
the way race conditions work is that
it is going to be some interleaving of
instructions
that results in
some bad state of the program or maybe
something
some that may have some security issue
related with it
so we know for instance that these is
allocated checks that we're doing
um all over the place are kind of there
maybe in some sense as a security
mitigation that we're trying to make our
program be secure
but due to race conditions due to the
fact that we're not just
executing sequentially in a single
thread but that we might get to execute
sequentially in multiple threads
you could think of it in some sense in
order to
if you want to check to see if there's a
race condition
construct the two threads like on paper
or whatever or like in emacs
i'm doing here and see if there's a way
that you can just
step through these instructions
in a way that violates the security of
the program
in a way that gets you into a state that
you
want
so obviously the cpu is going to execute
it as the cpu does
but due to context switches happening um
basically context switch is happening or
maybe
one cpu core running faster or something
these operations can start to be
interleaved in various ways
um it's not guaranteed for instance that
in thread one we're just going to
execute this and then in thread two
we're gonna execute this and then we're
gonna go back to thread one and execute
this and then we're gonna go back to
thread two and execute this
back to thread one and execute the next
one we're not just gonna like alternate
between these
operations for instance we might execute
all three of these and then execute all
three of those
we might execute like two of them and
then execute like one
and then execute like this and then
execute like two more like
there's all sorts of options that the
the cpu might go in
and for now let's just say that a
particular thread will be sequential
but the intermixing of this and you have
to think that this is operating now on
global data that is shared across all of
the threads
that we can have impacts on the global
data and put the global data into a
state
that the programmer did not intend for
okay so what we want
ultimately or ideally i guess i would
say is for
us to have a freed allocation
so let's just think back actually to our
our xsplit logic
what we really want to be able to do is
call scanf on
some freed allocation but the thing
preventing us from doing that
is this is allocated boolean
right we want basically for some
allocation to
actually be freed but
for the program to say that is allocated
equals true so if we can make it so that
so let's maybe say like goal
have a freed allocation
zero let's say like we're just working
on allocation index zero
i index zero but
is allocated zero equals true
like this would be great because this
would mean
that we could do a scanf over a freed
allocation
this is exactly what we want for
corrupting the metadata
um so there's a question in chat for in
twitch chat what challenge are we
discussing
um we're kind of discussing in some
sense
the current six levels that are out and
i guess also what will be the seventh
and eighth
level as well and then eventually it'll
switch over into a different direction
um we're just kind of discussing again
at a high level
uh view of how the challenge works
and what security properties we are
abusing
um yeah okay so our goal
as i said is to have a freed allocation
index zero but is allocated zero equals
true
so if we look at this program
sequentially it seems pretty likely that
the programmer
doesn't expect this state to be possible
right if we free something
the whole idea is that once we free
something that we set is allocated index
equal to false
right this is what we're doing this is
the
the whole idea okay so
how can we abuse this then
um
[Music]
let's see here
so we may actually need to have our
initial state so we're kind of assuming
let me move this after the goal we're
kind of assuming that this is our
initial state
um but we can obviously potentially mess
around with it like we could start where
we're in a situation where is allocated
index is equal to
true for instance let's see if we can do
it with this
so in order to get this state up here
that we're talking about basically
something be
freed we would need this operation
to occur and then this operation to
occur
and then um this operation to occur
um yeah and we need that order
specifically we actually can't
allow this to happen
before because then we would have called
free
um set it to be false
but then we would malloc it and we would
get that same allocation
back um which means it would no longer
be a freed allocation
and we need it to be a freed allocation
so this operation we can't actually go
like this
and then this and then this and then
this
what we want to have happen is we want
this so that our allocation gets freed
um we're forced to set is allocated
index equal to
false but then if the thread was hanging
right here
and we get to resume execution here we
could set is allocated index equal to
true
which would result in exactly what we
want once we have this um once we have
this situation
it's it's a win so maybe we'll uh
want to write the sequence of events
that we want
so we want this we want this
and then we want this
oops
um yeah and this is this is allocated
buffer
is of course as we keep saying um
is our um what am i saying
is is global data so it's kind of shared
across all threads
um yeah okay so this is the sequence of
events we want to have happen
so let's see here
so we can't ideally what we need
then to have happen is that at some
point we need to get
thread one to stall out after it
executes this
and then for us to go back into this
thread
and execute um okay
so if is allocated index is false
we can so if we're thinking about it
right thread two needs to get into this
so is allocated needs to be set to true
at some point in order for us to get
into this into this basic block here
and we're assuming that is allocated is
initialized to false as we said we could
actually
configure the program in a way where
that's not true but um
we can see here in thread one we would
be able to enter this block so both of
them at some point need to enter their
blocks
um
let's see here so this might be
not possible given two threads we might
need a third thread
doing stuff um
let's see here so
in theory we have it set to false
initially so we can enter
this block but then if we were going to
go and execute this
to make it true so that we could
actually enter into this block we would
have already executed
this statement and we need to stall out
on executing this statement
until after these two things have
happened
so we can enter this block execute
these two things but we can't just stall
out here and not execute this yet
we need to also execute this in order to
enter this so that's
basically our race condition here in
this configuration isn't going to work
okay let's consider maybe the opposite
case if this was initialized to true
in this case we can immediately enter
here
but then we can't enter here
because we would have to execute this
and this
right we would have to specifically
execute this
before we could enter this block
and execute these two things which means
we would execute this
after we executed this and this which is
again not an
order that we want so we can already see
that given just these two threads kind
of thinking about this at a high level
of how we want our race to play out
and we want the race to play out in
exactly this way
um again remember we can't have malik be
called in between here
that's not what we want um we can see
that just given two threads and maybe
initializing this to either true or
false isn't enough for us to make this
race condition happen
okay so let's we're able to have an
arbitrary number of threads
um what can we do then
let's see here so in my mind right now
i'm thinking like
what if we have some thread over on the
side
a third thread basically just constantly
calling malik and free and actually we
can kind of
guide our solution to thinking about
this high level problem
if we look at what yon's solution was
because of course yan's solution is
going to be implementing exactly what
i'm talking about at this high level
um so we can see
that in this loop he has r3
calling malik this guy calling
scan f this guy calling
free
so he doesn't actually have kind of
think of it as we have
one thread calling malik one thread
calling free
but then the third one is just calling
scanf
interesting
um oh
interesting okay so what i was
discussing before
um in terms of how we wanted to do it
so before i was saying basically that um
we want this line to execute then this
line to execute
and then this line to execute right this
is kind of the high level
overview of what we wanted the execution
interleaving to look like
and that we couldn't have this happen
right we just needed
this then this
oops and then this and that we couldn't
have this happen in between
but there's actually a way that we can
make be fine with this happening in
between
and the way that we can do that is if we
have some third thread just calling our
scanf logic
so if we do let's just copy this as well
um there is a way that we are fine with
it calling malik and the way that we are
fine with it calling malik or
yeah that we're fine with it calling
malik is if malik
um happens after the scanf
goes through so really what we're trying
to do right is eventually call this
scanf
to overwrite the forward pointer so that
um the t cache will be updated with
we'll basically have corrupted the
forward pointer and be able to
hijack it um
yeah okay so let's look then at
how can we do it with these three
threads given these three operations
happening
and i think it's really worth it with
race conditions to just like
conceptually think about how many
threads are at play what operations are
they doing how do we need
stuff interleaved this is like kind of
how you can get
race conditions to kind of click in your
mind
and this is the tricky thing is like a
developer writing a program and
using semaphores and stuff and trying to
make things efficient because there's
some
overhead introduced by using semaphore
so you don't want to like use them
non-stop all over the place because you
could basically end up making your
program just like
effectively single threaded if you just
go crazy with semaphores
as like the developer writing this
program you have to actually be thinking
through
these sequences of events that can carry
out and make sure that your semaphores
are set up in a way that
doesn't cause a bad sequence of events
um so as a security
person going after it we're kind of
doing the opposite right we're i mean
we're doing the same thing right we're
just interleaving events and seeing if
we can get a bad sequence of events to
interleave
okay so given that so we figured out we
couldn't really do it with three threads
we kind of proved it to ourselves
that given all of the concerns yep
there's a question go for it
okay so the reason we couldn't do it
with two threads is that
in the case where is allocated is
pre-initialized to true
how can we execute right so at some
point we need
these three things to happen in this
order right
and i keep saying that not malik
here for two threads and the reason i
keep saying not malik here is that if we
called malik here
we would no longer have a freed
chunk right does that make sense that if
we called malik here
we would basically free our allocation
and then we would malik and get that
exact same allocation
back that we just freed which means we
wouldn't have
a freed allocation um
set where is allocated is true does that
make sense
okay so yes we can't call
malik here and the reason then that we
can't do it with two threads is that if
this is initialized to true
we can enter this and to make these
things happen we need to basically enter
both of these blocks at some point we
need to pass the
is allocated versus is not allocated
checks in order to execute the code
inside
so when it's initially true we can enter
this block so
maybe thread two steps forward executes
freed
and then we can execute is allocated
and now thread one is able to enter
because we just set is allocated to
false which means thread one could
theoretically enter here if we decided
to resume execution on thread one
but we're going to call malik and it's
an issue and that's the only way we can
do it
and then if you set it to false the
opposite is true basically if we
initialize the false
we're allowed to step here we can't step
here because if we stepped here we would
basically no longer be executing these
two things so we would
step here we would malik we would set is
allocated to true
and now thread two would be able to step
in order to actually execute this code
but it would go in the wrong
sequence of events um so two threads
just doesn't work for us
um okay so
but we can do it with a three threads
and the way that we do it with three
threads is that we're actually fine with
malik
executing as long as this scanf gets its
logic in in the right order
so let's look at a sequence of events
across all three threads where we're
perfectly fine with what's going on
and i'm not entirely sure off the top of
my head whether we want this to be
initialized to true or false i'm going
to
guess false but it might need to be true
but either way let's try and see if we
can step through in a way that abuses
this program
um and the way actually let's go back
the way that we can now abuse this is
as i keep saying we're now fine with
thread one calling malik here
in theory um and we'll say that this is
thread one
maybe we'll add some spaces make it
look cool this sequence of events but
this isn't quite enough
um what needs to happen in between these
two things now um
oh i guess this is uh this is
interesting okay so what we need to have
happen here
is that we need to pass this check
well maybe we won't specifically say
that for now what we want to have happen
though in between here
is this right here in our third thread
our third thread needs to call scanf and
if we call this
scanf before the malloc happens now
we've corrupted
the forward pointer in here and we've
made it so that the
after this malloc goes through um the
tcash header pointer is actually going
to be
pointing to whatever we just scanfed in
so if we can sneak this
operation in in between we're fine with
this mallet going through
does this make sense to everyone this is
like critical to understand that this
sequence of events
results in a corrupted forward pointer
where now we
basically control where malik is going
to send uh what address malek is going
to return
this is like critical this is the the
crux of everything basically
that these five events happen in this
order
um is what allows us to corrupt heap
metadata
control the forward pointer and now have
an
allocation wherever we want it to be and
once we have an allocation wherever we
want it to be we can either
print f from that which means we get to
leak arbitrary data
or scanf which means we get to overwrite
arbitrary data
these five events happening in this
order is exactly what allows us to
abuse this program hopefully that makes
sense
um so is this possible it does that make
sense sorry what was the
question
um so i'm not even necessarily saying is
this possible
we have to now figure out is this
sequence of events possible but do you
at least agree that if we were able to
execute
these calls in this order that we would
corrupt the forward pointer
with arbitrary basically we would get an
arbitrary forward pointer which means
an arbitrary allocation does that make
sense
so again i'm not even asking if this is
possible
so maybe this isn't even possible but do
you agree that if these
five operations occurred and we can even
maybe like
temporarily ignore these two things
right
if these three operations occurred
do you agree now right that when we call
free
we have a allocation sitting in the t
cash
we call scanf over that allocation
sitting in t
cash we basically get to overwrite the
first eight bytes of it
and then malik goes through malik
basically reallocates this allocation
that was freed
but now the head of t cash is pointing
with those eight bytes that we set up
does that make sense right this is
exactly what we
explore in uh in baby heap okay so that
is if we can cause that sequence of
events to work
we will win so let's see if we can do
that is there a way that we can step
these three threads forward
given whatever initial configuration of
is allocated we can probably make this
be
either true or false um setting it up
let's assume it's false because that's
the initial
state of the program um okay can we step
this forward then
so we need to
um so is allocated so we can't step here
because
is allocated is currently false um
that's fine but this guy
in theory can step forward
i'm thinking that we don't want to be
initialized to false just looking at
this
okay so let's assume it's true instead
so let's say
um something was already mallocked for
this
index maybe we just set it up made it be
true by calling malik at the start
which basically initializes to true then
we already have something malloc or
whatever that's fine
so if this is already true what can we
do
we can step forward in this thread
so you basically enter the basic block
that we wanted to
enter so we're able to be executing here
in thread 2 now
we can step forward here
and this is now executing in thread
three because we basically
is allocated is true so we were able to
walk through both of these
um okay
so
now how do we want to execute
so we want to execute
as we said we want free to execute
um and then this and then this okay and
we're already set up right now
to where all three of these operations
can execute right
so and maybe even more simply let me
actually
back this up and like let's start by um
at the initial configuration
uh yep okay so the other thing to note
um even though we're saying basically in
order to figure out if a race condition
is possible
ideally we're not um doing like a single
instruction and then going to the next
thread and doing a single instruction
because the cpu is
probably not going to let that happen we
can probably context switch
it's theoretically maybe it's possible
but
it's the more times you rely on your
threads context switching around the
less likely it is
oops so let's see if we can get this in
a very efficient
order of execution that's not super
critical for
it actually technically being possible
but let's just
walk through ideally with as few
switches between the threads as possible
so let's say we go through we execute on
thread three
we're just going to switch over to this
um and that like returns true or
whatever so we're fine
to continue executing um
actually hold on that's not what we
wanted to execute first we wanted to
execute thread
2 first we
want to all right let's let's ignore
this efficiency idea for a second here
so in thread 2 we we execute this
and then we execute in thread to
our free condition so free
allocations index so now
these two operations have executed in
thread two
which means this is pointing
here actually hold up my headphones are
starting to die let me just uh
remove one of them hopefully that's good
enough let me make sure
[Music]
it's not completely dead yeah it seems
fine okay um
so we just executed these two operations
and then let's say we context switch
into thread three executing
and we execute this operation in thread
three
and that's going to return true because
we haven't changed the value of this
variable yet
so that returns true
and then we execute let's say
then let's say we execute our scanf in
thread three
um scanf executes so we did our free
we did our scan f okay and then thread
two goes back and executes now
and sets this to be um
false so that two
executes this gets set to false
okay so now if we update everything
that's
executed we've executed everything that
needs to happen
inside of thread two we've executed
everything that needs to happen
inside of thread three and now let's say
thread one resumes
and when the thread one resumes it now
does its check
and this returns um i mean i guess we'll
say it
not is allocated returns true so we're
able to enter into this block
and then we execute these two things no
problem
okay so through this sequence of events
which is
totally possible um if we interleave we
can kind of think that basically
we executed free and then
or maybe like we passed this check in
thread two we passed this check in
thread three
and then thread two does it's free then
thread three does it scan
f and then we decide to make this now be
false and now thread one is able to
theoretically pass through this and do
its malloc so what we just did
we can see and i guess maybe we don't
completely care
about this because we didn't exactly get
this sequence of operations
um we can see that this is kind of out
of place but that's fine
ultimately what we really care about is
the sequence of free scanf and malik
um yeah okay so if we just kind of strip
away
all of the maybe unnecessary stuff and
we just showed that this is possible
we got this sequence of events
right and this is exactly what we wanted
in order to corrupt the forward pointer
so this shows that it's possible
okay so now let's look at what yawn
wrote yesterday or
wednesday during the extended q a um
this maybe will start to now make a lot
more sense
okay so
um what did he
do so he
called
malik and then free
um which
theoretically would initialize this to
be false
which isn't actually what we want
um but in theory this is
executing out of order because this is
going to two separate threads
so i'm not exactly sure what's going on
here let's kind of
ignore it for a second let's just
pretend that this guy
stalls out this free operation i don't
fully understand this
oh no but that's not an issue okay the
reason it's not an issue so let's say
that
that um is allocated is still false
after this we do a malik we do with free
for some reason the reason or for some
reason he's setting this up
such that thread three basically gives
us our malic
and then we decide to introduce that
into thread one's
t cache but
that's fine that doesn't really matter
the more important thing though
is that we can see that we have this
while loop and whenever you see like a
while loop in this racing
sort of situation like we're basically
just trying to get a bunch of threads
executing as fast as they can doing a
bunch of operations
until eventually we interleave in
exactly this way
or maybe an equivalent way that is just
as bad um
okay so we call malik
um which would initialize us
if we assume that this succeeds um
this is the yeah exactly this makes
sense okay so we call malik right away
um and we clean which kind of means
we're like gonna wait a little bit which
means this is going to happen
like guaranteed basically in this order
like malik is going to have happened
so now is allocated is set to true which
is what our attack relied on
our conceptual attack relied on is
allocated being set to true
um let me switch out my headphones since
i don't know if they're going crazy and
dying or not
hopefully not that would be very sad um
anyways so we've got
is allocated our precondition of it
being true
now being true because we just did this
um this operation we did a malek when
doing a malek makes is allocated true
okay so
um and it makes it true right because
oops
it makes it true because this is the
malik logic right at the very end it
sets is allocated to true
okay so now we fork and the reason we
fork is that we want to
start performing operations
um concurrently so even though we're
sending
in theory this would still work even if
we didn't do this in a separate thread
it's probably just going to be much less
likely to succeed
and the reason it still could work is
because we're sending
all of these things kind of like over
the network and who knows what order
they're going to arrive
in and stuff can be interleaved or
whatever
but this increases the odds because
we're making it kind of happen in a
separate process we're making it
happen um yeah in a separate process
it's going to happen at the same time
so we're calling free um so you can kind
of think of this
we're calling free it turns out in
thread one but you could think of this
as being our thread
two so maybe we'll uh call this
r1 we're basically spam calling free as
much as possible
um yeah okay so
we're calling free a bunch of times and
then also we're calling
scanf a bunch of times with packed and
what is packed
packed is phone p64 address
and palm p64 address is the address that
we're trying to make our allocation go
to
so we are calling this in
r2 based off of the exploit
um okay
and then we are
waiting okay
and then we're basically checking to see
if we succeeded
so the first time around we're
definitely not going to succeed because
we will have called malik in order to
set malik's is out
basically to have set is allocated to
true
um and then we go through and execute
these which means we won't basically be
able to have
executed malik again at the end but
that's fine this is just the first loop
through
um and then so basically we're trying to
check to see if we succeeded
and the way we do that um the first
thing we do
is we print f our index
uh so we're all of the way through this
index is basically working on allocation
zero for instance at the start or in
this case i guess allocation one because
index is initially one
and then we increment that later on for
a reason i will explain later
um we're just working here on this
um so we are always working on
allocation one
so we print it and we see if it returns
none to us and as we said before let me
see if i can
go back up to this it'll tell us
none if is allocated is set to
false
so we are assuming that is allocated is
set to
false because we're assuming kind of
like these freeze will have
um basically executed it at the end
a bunch of times basically the idea is
that we will have
malik and then freed
afterwards and a bunch of freeze will
have happened
and that is allocated will be set to
false so that's why we're asserting that
none is in result
okay um hold on
yeah okay that's fine
um so that's why we assert none is in
result here
but then what we do is we call malik
again
and we print f let's see
[Music]
malik we printf and then
we read in that data to see what the
message returned to us
and we're basically saying okay what
we're basically saying here
is we're checking to see if we succeeded
and the way that we will have succeeded
is that
if we call malik and printf
and read until message
if this returns to us the address that
we're trying to store here
so if we go back to this logic here
so we have this scanf and the scanf
operation is accompanied by
us trying to force our allocation to a
particular
address um and that particular
address is actually in
um in here we will have succeeded
um let's see
so in this situation
oh like okay i understand now so the
reason
that this works is that um
we call malik which
will um actually hold let me
jump ahead to see how we finish out
so an r3 we call free
zero and then we malik
zero or malik one freeze one
um
three
so
let me think here for a second why
this matches up with our conceptual
attack
so something to note is that this free
will only succeed once even though we
send free 2 000 times
it will only work in the instance
where is that so well basically i mean
theoretically it could work more times
uh actually no that's not true it could
only work one time the reason it can
only work one time is because
this free operation is always happening
on the same thread
and it will succeed when is allocated is
true
because then it will go through and it
will free
and then set it to false and once we've
set it to false
since all we're basically at this point
in time all we're doing is freeze and
scanfs
and scanf doesn't control is allocated
it doesn't change the value of this um
when is allocated is true the free will
go through and set
is allocated to false and then all
future
of these 2000 attempts will fail it just
basically will be a no op it won't
happen because is allocated will be
um is allocated will now be false which
means it'll it won't enter here anymore
so this operation here even though we
sent it 2000 times will only succeed
once
and this scan f
in theory could succeed multiple
times
yeah there's no problem with that but we
would be constantly overwriting the
same thing
um
i'm really curious about like changing
up how this control allocation works
because i think it technically will work
but i think it's maybe a little more
tricky to look at than it needs to be
but maybe i'm missing something
um so the way i see it
is that basically we
well let me let me keep looking at it so
eventually we call
printf index and we
know that assuming that one of these
2000 freeze succeeds and sets
um is allocated equal to
false which i think must happen
because
[Music]
it's very likely to happen i'm almost
certain it must happen
um and once is allocated is set to
false now this printf is going to spit
out
none to us
okay and then
we malik
and then we print f
um and this
when we do our malik
we will get back
um we will get back the allocation that
was freed
uh is that true actually hold on so
because it depends on the thread so this
r1 is the person doing freeing and then
eventually r1 also does the malik so
we're working on its t
cache um
so that will be the same guy that got
freed
here um
and once we call malik the first eight
bytes won't get
modified because that's not what malik
does but the forward pointer will still
be
sitting there
and then we print it and we see if we
successfully
corrupted that forward pointer
um
yes okay so this makes sense right okay
okay i was
definitely getting confused there for a
second it's definitely uh
it takes some work to think about this
okay so the thing that we're not like
tracking in terms of while we're
stepping through this code
is what t cash can look like at all of
these points
so t cash is going to
at this point once we do let's say this
this printf basically after yeah like
right in here
tcash is going to look like
our freed chunk
um and then that will be pointing to
aka what the first eight bites of that
freed chunk are
will be um packed
basically this the address that we're
trying to make it be
so the first thing we do is we printf
and we see it says
none which makes sense because is
allocated is set to be
false and when is allocated is set to
false as we talked about
a long time ago at this point uh it
prints out
none if is allocated as false
okay and then we call malik
and when we call malik that is going to
return to us that initial freed chunk
but it's also going to update t cash to
be our packed address
so that's basically going to be the next
thing that comes out of malik
okay and but that those eight bytes are
still sitting
in this free chunk even though we've
updated t cash which it would be a waste
of time basically to
change the first eight bytes to no
longer contain the net forward pointer
might as well just keep it there as
uninitialized data because that's
quicker
so we actually go on to printf it so we
we malloc it which updates t
cache to be now the next thing will be
packed and then we print f
that free trunk printf freed chunk
which is actually going to spit out to
us packed
because that was the forward pointer
and that tells us once that is true that
our
sequence of events was correct because
this means at this point
at this point that we were able to see
that pact is the
the result
that means that inside of t cash
t cash the next thing in line is this
packed address which means malik is
going to return pack to us
okay so this confirms that we're good to
go so we can break out of this wild true
and the reason that we need to loop this
is because this is a race
um it's yeah it's a race so
we need to basically get the right
sequence of events we need
basically the this sequence of events to
occur so we're just kind of looping
until this sequence of events occurs
and we're able to check that this
sequence of events occurs
by printfng the free now malik chunk
and it returning back basically packed
back to us
um at least i think that will work it's
certainly sometimes works but but
apparently we've already seen that this
exploit sometimes fails so maybe that
check's not exactly
correct but it seems mostly correct
um okay and then what do we do
we call on r3 we free
um
[Music]
we free but we free to our okay this
makes sense we free to r3
um just for the sake of doing it i think
this probably keeps
the cache consistent in our connection
i'm not exactly sure why we need this
it's i don't think we need it um
but i well we might need it to be able
to basically call controlled allocations
multiple times so basically what this is
going to
um free and notice how instead of on r1
so basically every single r we have r1
r2 r3
each of them has their own t cache so
when we call free in malik we're
operating on
that person's t cache so even though we
called
malik and got our allocation here on r1
um we're freeing it back to r3 so we're
not actually messing up
r1's um t cash which means that this
t cash being packed is still true so we
basically just take that chunk we got
and send it back to r3's t cash which
might make sense because yeah and this
is why
at the beginning of this we call malik
from r3 because we're going to get that
guy back
if we call controlled allocation again
because this is now going to be the
person sitting at the
the top of t cash for r3 so we send
this allocation back to r3
but now the next guy in line still r1's
t cache
is still pointing to pact so when we
call malik here
we are finally going to get our
controlled allocation which means
basically the whole point of this
function is to give us a controlled
allocation to a specific address
and we have succeeded at this point um
okay so then what do we do so we when we
want to do an arbitrary read we do a
controlled allocation we've just
forced an allocation to be where we want
it to do as discussed over the last
one plus hours
okay so then what we do in order to get
our arbitrary read
is we have our forced allocation
pointing at pact or whatever address we
wanted it
to be allocated to and we call
printf and we just read until message
and then we
read whatever data is there
and if we pointed this for instance at
secret adder to do our arbitrary read
um now we've just read
um the first eight bytes and the reason
it's the first eight bytes is because
the second eight bytes in this is going
to be our
um it's gonna be nulled out because
that's what malek
does because initially there was when
it's freed there's a key in there
and the key basically keeps track of
preventing a double free from happening
and then when you call malik it rolls
that out to say basically it's no longer
freed
um so that's why you can only get eight
bytes but you can just perform this
again because the secret doesn't change
and we've already seen now um let's uh
go ahead and run this it doesn't
completely it's not
a hundred percent consistent i guess it
worked here we saw before though that
sometimes
we're leaking null so there's some
quasi issue with this exploit or maybe
it's just that since we're only
who know i'd have to look further into
it somehow our race
isn't guaranteed to work and i think
there's
potentially some ways that we could
clean up the exploits and make it
guaranteed to work but maybe i'm wrong
about that idea
but either way it sometimes works um
and when it sometimes works we can get
our secret and then you just need to
leak the second part of the secret send
that off and you get your flag
and all six of these levels basically
follow this concept
but leaking memory around in different
areas
so um
yeah that's kind of the idea and yawn
kind of has already talked about in his
q a some of the
other areas how you can start leaking
them
so it's actually something that i
created that might be
interesting let me see
if i can get it to work
hold on let me leave
this um the
projects um
ls mem scanner yeah this okay
so i created this thing that might be
interesting to you guys working on these
six levels here for understanding
basically pointers and memory it's kind
of just a very simple tool
um we'll just kind of maybe print it out
mem scanner memskin
dot pi it basically just goes through
and finds pointers in memory regions
pointing to
other memory regions so what do i mean
by that if we
run if i go into mem scanner
um my example here was
just like bin sleep we'll just have that
run
and then we run this mem scanner
against this pid that basically just
takes in a pid
and i just have to enter my password it
just
goes through and finds pointers in
a particular memory mapping pointing to
a pointer in another memory mapping
so for instance
the binaries read-only
section here has a pointer that goes to
libsy
so that means that if you knew where
this page was
and you were able to start continue
doing arbitrary reads inside of this
you would be able to get to libsy
if you knew this you'd be able to get to
the stack
if you knew this you'd be able to get to
libsy again another way you get there
and if you knew like some stack
addresses for instance you could get to
ld or you could get to lib c
the important thing for these levels
once you've got
your arbitrary read working and it kind
of makes sense to you
is going to be pivoting around in memory
so say
you have
some let's say some
pointer or let's see here
let's say you know where lib c is but
you need to figure
out where
the challenge binary is at because if pi
right it's randomized
and maybe you want to leak something in
the bss
where you want to leak something in the
bss
where pi is turned on so level one pi is
turned off but let's say it's turned on
but you know where lib c is if you can
find a pointer in lib c
that points you at the binary
so for instance this one looks
potentially promising
um but if i know where libc is
i can read out this address or i guess
this address if i do an arbitrary
read here the data will be or what it is
what the the contents of the value is
will be here
which means that if i read out this
memory address now i know this memory
address and if i know this memory
address now i've just broken pi
um so these levels are going to kind of
force you to
pivot around in memory is going to be
kind of the general
idea going forward but i think this
once you have your arbitrary read and
arbitrary write mechanism
it'll take some thinking to figure out
kind of how to pivot around in memory
um maybe some reading and kind of
understand what's going on here
but i think the much trickier part is
getting your arbitrary read to work so
once you have that
hopefully you'll find it more enjoyable
pivoting around in memory which is a
very useful
skill okay so are there any
questions i'm going to start wrapping up
office hours because i think what i've
explained
basically covers everything at play
within these six levels
um so yeah are there any questions um
before i
yeah yeah
i so if you um
are you just like git clone or
https github
dot connor nelson slash
mem scanner is where it's at um maybe
you'll find it useful maybe
you won't um i don't know it basically
the whole idea is i was just thinking
about
the idea of
figuring out where a pointer
in one memory region is that will bring
you to a pointer in a different memory
region
because that's kind of what these levels
are going to be all about
so you can either just like kind of sit
there and scan through memory which is
what this tool does in order to figure
out for instance that there's a pointer
in libsy that points to the binary
which basically means that if you had
already leaked out the address of lib c
that now if you given an arbitrary read
you could leak out the address of the
binary which kind of breaks pi in that
case
or all sorts of things basically if you
have the heap you could get to
um lib c if you have a pointer inside
the heap
you can get an arbitrary read again now
you get to lib c and then you get from
lib c
to binary you get to whatever basically
you
pivot around and memorize the idea if
you're interested in this tool maybe
it'll help you maybe it'll
not help you i don't know you can get it
from there
um okay are there any more questions and
maybe this will make more sense once you
start working on like level two and
level three
but uh i think once you've solved level
one you're in a very good place for
solving
the remaining levels there will be more
tricks involved in terms of pivoting
around in memory
but getting your arbitrary read
primitive working
is like in my opinion the most tricky
part of these
levels here um yeah from there it's
figuring out how to pivot around in
memory
any more questions
all right i will take that as a note um
if you
do stumble into a question uh feel free
to ask in the help channels if it's
super super specific and for some reason
you can't ask it in the help channel
feel free to either email us or message
me on discord or whatever the same
same policy as you know we've been doing
this whole semester okay all right uh
thank you for attending my office hours
and
good luck on the challenges