here so the first goal is to
basically get around a filter for
instance
not being able to uh if we weren't able
to use the
breakpoint instruction in three
what we could do instead to not have
that byte appear in the shell code but
still
ultimately get what we want in uh
executing that instruction
so normally what we're uh looking to do
here is to call
this um
uh yeah okay
which one compiled should be a cc
uh and it is okay um
so let's
um
for now let's just write this out to a
shell code file
um and then we can send that off to
program to see that what we want to
happen is happening
um okay so
we will i will call it shellcode
um
then we will write that out
and make it exist
okay um
that creates that and then if we
background this
and we run baby shell level one uh
teaching one
with um that shell code file
we'll see that it is executing our
into three instruction and this is the
most important thing to know that it
actually worked is at the end it says
break point trap but of course the goal
now
is for demonstration purposes is what if
we're not allowed to have this cc byte
appear
um okay so in that case
something we can do is that we can
basically we want cc to appear
we're not allowed to have that but what
we can do
um let's see here does this prefix work
i don't remember uh
it's not through c3 cc
yeah okay
so that works
but obviously we're not allowed to have
a cc um
so if we go to cb instead and then we
just increment that byte
uh that should have the same effect
um let's verify that though
okay um and then
we run this we will see um so now our
first instruction
is to increment the byte at rip so rip
of course is our ins current uh
instruction pointer
um in the context of when this
instruction is executing rip is pointing
to the next instruction um
and that next instruction is this ret f
instruction i don't really know what
red f is meant to do but the the goal is
that it's one value away from our cc
instruction that's going to do
uh this breakpoint trap uh so this
executes
and then it increments this to cc uh
just to
actually let's go i think here
we can't as trace can we oh wait we can
hold on i want to show this in
gdb and we'll ignore it we can
uh could you show the assembly code
again yeah
um well we can run it and see what the
uh it's telling us our assembly code is
but if you wanted to see
how i was doing that in python this is
what that code is uh is it possible to
solve baby shell level 13 without rob
yes it is definitely possible to solve
all of these levels without rop
the goal of this assignment is strictly
shell coding so
i think i guess you could use stuff like
rop and other
exploitation techniques that we'll get
into later in this class
and it might i guess some ways make some
things easier
probably not but it's definitely not
required
okay so we had another question that was
about
multi-stage shellcode is that right
someone want to know about that
okay um okay so in general
uh the the concept of uh
multi-stage shell code is that we are
going to
um basically read
into where we're about to execute so
what that means
um is
let me pull up nice
syscall table actually you guys won't be
able to see it anyways never mind
uh but it's just called zero is to do a
read
um so if we move rax zero
and then syscall that would be a reasons
call but we need to set up
our three arguments to read where the
first one is the file descriptor we want
to read from the second one is the
buffer that we want to
read to and then that third one is the
number of bytes
okay so uh
rdi needs to be this file descriptor
that we want to
read from which is zero
rsi is the buffer that we want to write
to
um which would be
um do this
it needs to effectively be around rip um
and then the last one is the number of
bytes we'll just make it a thousand
so um our dx a thousand
and then so the thing to realize though
is that we're moving rip
in to rsi right here uh so really
from the context of when we start
reading in we're basically going to
start overriding this instruction but
the thing to remember of course is that
this instruction has already executed
as we'll have this instruction i've
already executed but the first few bytes
that we're going to be reading into
aren't going to be the next executed
instructions they're going to be filling
up this memory of
instructions that have already executed
um
so if we uh
let's start by doing this uh what
complaining
support construction
funny about this one
[Music]
hey
i'll use load load effective address
um
okay that makes sense right okay uh
did you solve it without rob yeah we
definitely solved
all of we have solutions or solutions
for all of these challenges without any
rob
um okay so that would be stage one of
our shell code
um if we're interested in uh stage two
um we'll just call it shellcode2
[Music]
let's see here what do we want to do i
guess i can show you guys the
the fact that pawn tools does have very
nice
things for in general um
allowing you to basically assemble all
your instructions without having to know
about it
so i think it's read file yeah
so it has the ability to do this read
file thing which will just
generate all of the assembly for you
obviously this doesn't work in most
cases but for a simple stage 2
shell code we'll just use this as a
demonstration
and where we want to go is just fd1
so if we print that you'll see that it
kind of just
builds up all of this shell code and it
actually kind of tries to be nice where
it like doesn't include null bytes
um but it's not going to help you for
any other level so i
definitely in general would not
recommend using this strategy it's just
uh
it is something nice to to know exists
okay so anyways let's make that our
stage two
copy that
and then uh you'll see that this won't
actually work based on the what i was
talking about before where
um we're reading into the wrong part but
i'll just show
that it doesn't work real quick and then
i'll show how to fix it
um so if we
start by how do we
need
you know it's rather than think about
how to set this up let me show you how i
would
actually do it using more functionality
with phone tools
so we can do
we can create a poem tools process using
pwn.process
and specify the path to that process
so this gives us
our reference to the process that we can
start interacting with
actually let me put a slash in front of
that real quick just to make sure
okay um and then let's get our shell
code again rather than have it in files
let's have it in
variables uh so this
let's make this stage two
okay and then let's get our stage
one
is this
okay so now we have our stage one shell
code our stage two
and we have uh this representation of
our current running process
um so something to
realize is that before um
it's here before it executes our shell
code it goes ahead and lets
us know executing shellcode um so the
issue
and the reason that i'm demonstrating
pwntools rather than figure out what
exactly i'd want to do with cat
to make this work is um
basically we need to send a bunch of
bytes uh in a single
units that's going to become our shell
code for stage one and then
after it's executing and once we call
read again we need
our next set of bytes to enter that read
call if we just cap the two together
they'll just get smashed together
and stage one and stage two will end up
here
which is not at all what we want we need
these two things to be separate
otherwise it won't work
which may be where some of you have
gotten caught up
so if we start by
just to kind of show i guess what
ponzules is doing we can read
40 bytes for instance and it
tells us the kind of this welcome
whatever thing
and then we can instead now write to it
so if we want to start by writing stage
one
and then we can read another say 4096
bytes
we'll see that it's about to execute
shell code
and then we proc right stage two
um it's going to now send that off
because we're doing a read sys call
um and then if we do proc read 4096
uh it fails uh it's sag faults
so and when we kind of talked about that
we know that it's going to fail
so if we go back to stage one equals
this
um remember how i said that when we're
loading in this rip
we're basically pointing at this point
in memory this is like
uh i don't know like six bytes or so
uh basically the first six bytes of
our stage two is not actually going to
be
executed because we need to start
executing kind of like after this
syscall
um i don't know how many bytes exactly
it is we could
figure it out but otherwise you can just
send like 16 knobs and
assume that's good enough uh so if this
is stage one
um we can let's run through it again
just from the start process equals this
proc dot write state or let's start by
reading again
4096 rock.rightstage1
proc.read 4096 proc.write
stage 2 except instead of doing stage 2
we
include a bunch of knobs before it so
we'll just
include 16 knobs so that we have more
than enough room
that we're not having our instructions
be in
a region that's not actually going to
end up getting executed
and then if we do proc read 4096
we'll see that the flag pops out
obviously don't submit my flag
not a good idea um does that answer your
questions on doing a
two-part shelf code
yep i'm uh assassin in the exact same
way you would be
yeah i don't exactly know
how you would do it with cat it's got to
be possible
but somehow you would need
to like cat and then include standard in
and then like paste in or
maybe you can do like a cat sleep cat
like
piped in or i'm not sure it's it's
almost certainly possible of course but
i think it's a lot easier to
conceptually reason about just kind of
writing a pwntool script
i yeah for some i mean it's 4096 is just
a thousand x thousand i don't know it's
it's completely arbitrary yeah
it's a page of memory and some things
are like page aligned when they start
i don't know it's just a habit for some
reason i always just do 4096.
yep um
okay let's see what other questions
there all
uh let's looking at the twitch chat real
quick
[Music]
no idea how can i exploit with just 12
bytes and no writable memory
i am stuck at that challenge out of all
ideas
um okay so
i think here what what to say without
just giving everything away
so obviously when you're constrained to
12 bytes you need to be doing lots of
instructions that are
super minimal so obviously for instance
you're not just gonna move like
eight zeros into rax in order to zero it
out right you're gonna do like
xor stuff john talked briefly about like
using the div instruction to be able to
like
efficiently zero out a bunch of
registers um
the other thing though to realize is
that you have
uh control over this environment right
so
for some of the shell coding challenges
you might have been calling into like
bin sh even though i guess that would be
difficult because it would drop
permissions unless you
set it up correctly um but you can call
any binary right you
you could create your own binary for
instance like yawn has been demoing this
like cat flag binary
um and executing that but you can also
i mean it doesn't have to be called cat
flag right we're trying to save space
you can uh
you can shrink that up to uh for
instance one character
um and to really uh
help with the hints you can make that
one character a very
specific character that might help you
shorten your shell code
that's probably the most hints that i
will give for
level 13. um
and for 14. uh i think yawn gave a
really good hint yesterday for 14 which
is basically
um understand that your
process lived a life before your code is
executing
investigate what is in that
what's in its history what's uh what are
in the registers what's in memory what
can you
abuse that's already there um
maybe i don't understand but how would i
get proc to work it says
it's not defined uh okay so
just to i assume you're talking about
pen tools
this is what i'm doing when i create uh
this proc
before i start reading and writing to it
yep
okay um could you go over syscall
alternatives um
so earlier in this office hours i was
showing you
how you could um
do something instead of the int 3
instruction which is
xcc by making it hex cb and then
incrementing it
that is certainly a that's that line of
reasoning is a
syscall alternative um
could you still not clear to me
the high level of multi-stage shell code
could you elaborate again
yeah so um stage one
uh so multi-stage obviously you're
saying multi-stage there's two stages or
multiple stages
so the first of those stages is uh
basically saying
okay so so the thing to realize is that
this challenge
calls the read syscall in order to bring
in your shell code right
this is how your code is entering the
program and
ultimately getting executed
so we're going to basically do the same
thing right we're going to call
read so that we can get more shell code
in
so all that stage one does is said
says uh give me a thousand bytes from
standard in
i want to read in a thousand bytes from
standard in um
and i want you to dump the contents of
those bytes that i read in
at the current instruction pointer
where the current instruction pointer is
kind of up here it's like six bytes or
so before
after the syscall so obviously we want
to start executing after the syscall
happens for stage two
um but when we put in this rip we're
kind of pointing to right here
um so the stage one says i want to take
in more bytes
and the goal is that suppose like all of
these bytes that were in here
like there's no issue like maybe for
size reasons or like uh
certain bytes can't exist for whatever
reason
we can insert this stage one to set us
up for arbitrary stage twos also
depending on potential more restrictions
but in theory doing a multi-stage is
kind of allowing you to get around
restrictions present on stage the first
bit of shell code
so this means we're going to read in
more
fights and then what i want to do with
stage 2
we see is i send it as stage 2
16 knop instructions so that's to deal
with the problem of
uh we're overwriting previously
executed instructions that aren't going
to get executed again so we need some
knobs in there
uh and then stage two uh we're just
using
shellcraft so this is just kind of like
a nice utility for just constructing
shell code for you of course don't rely
on this
aggressively in the homework because
it's going to you need to understand how
to write assembly
but we're just giving it now for stage 2
shell code that will allow us to read
slash flag and send it to standard out
so you type the stage 2 part into
standard in yeah exactly so
the program calls read for us the first
time
to get in our stage one shell code and
what we make our stage one shell code
is call read again to get in more shell
code
so that also will end up going through
through standard in it's just in a
different uh
read execution read syscall execution
it'll go in
um okay
let's see
length for a binary path can be slash
temp slash a right
so it already takes half of the space i
cannot place my cat flag binary in slash
or in
the home directory so you can place it
in the home directory obviously if you
include
um the characters necessary for saying
it's in the home directory it's going to
take more
but something to realize is that you
don't have to run
baby shell from here right you can go
into your home directory
and run baby shell from here and now
your current working directory is in
your home directory which means anything
that you specify
is in that directory right so the the
current working directory of this
executing process
is going to be the current working
directory of your shell when you call it
um so you don't have to worry about
where you can or cannot place your
binary
you can place wherever you want and just
make sure that this process has a
current working directory that you
want it to be
um more questions oh
looking at zoom real quick
how would one investigate the registers
of the previous process
gdb on baby shell level 14.
yeah so you would uh if there's time at
closer to the end because this would
take a little bit of time maybe
i'll look at this in a little bit um but
yeah gdb
uh would show you the registers before
your shell code executes
actually i can show you that um so let's
do with open
and we'll just go far back
okay so if i make this be my shell code
um i'm not going to show you level 14.
it'll be the exact same thing though
um so if i now go
and run gdb um
baby shell level one teaching one
um and i do start
and i specify that i want my shell code
to be what
enters in as standard in uh start for
shell code and then
i just hit continue um
actually what happened
hold on
why is it not picking up my instruction
all right whatever we'll just uh
do this insane process of
seeing where we want to break
[Music]
let's see here okay so uh this will
become clear
as we kind of go through more and more
things uh eventually there will be like
a reverse engineering module
uh that might help explain some of these
things but basically this is
dereferencing a register and calling it
which is a
pretty big hint that it's going to be
calling our shell code because our shell
code isn't going to be
like a function that just already exists
in the binary
so this is where we want to break
ultimately it's the the conclusion from
that
[Music]
so if we break there we continue
we can see that we are about to jump
into this
if we step we can see that we are
executing uh here and level one
it's not just at uh elite and then zero
zero zero
it's uh at a random address um
but we can see that what we're about to
execute is that in three instructions
we're about to execute our shell code
um i think it's info registers
yeah so for instance if you wanted to
know the contents of all of the
registers
in memory you type info registers at
this point and you can see
kind of ineffectively the history of
this program at least as it relates to
where we're currently executing so i
guess the thing to realize right is that
all of our registers aren't just like
zeroed out before we uh
enter our shell code these registers
have values and these values might have
meanings
that could be useful for it or it just
might be useful for instance uh
that rax is zero for instance um
kind of depends what you want your shell
code to do but
so for instance like in some cases you
might be zeroing out
rax in your shell code if we know that
rax is already zero
like that's some saved bytes right we
don't have to zero rax out it's already
zero
so things like that are things to think
about
um how does syscall get called is it
just one rip
on 0f05
um
i guess i'm not i can interpret that
question
like why does it i mean why do any of
these instructions do
any of the things they do like why does
a move eax and
like zero into eax move zero into eax
like the processor deals with this
basically um when it gets the syscall
instruction it has a um an interrupt
uh handler table that it basically can
the kernel takes control at that point
uh it gets an interrupt effectively that
puts it into kernel space the kernel
analyzes to see
oh zero is an rax we want to do
a uh read syscall and then the kernel
dispatches that
it also before doing that saves all of
your registers so that it can restore
you um back to your state
it's basically uh i would recommend
taking an operating systems course to
kind of understand how it is that uh
syscall works
um or if i missed this but how do you
pass two stage shell codes
baby shell binary um yeah so i
down or look at the video after that is
uh definitely something we talked about
if you have more questions after
watching
um that feel free to send a name
does it overwrite the so kind of quick
uh the video will be this one we've
talked about it earlier in the office
hours it'll be available on youtube
and also on twitch um
so just also quickly going back to stage
two uh about questions related to it
does it overwrite uh yes it does
overwrite some parts of the existing
shell code so
if i um
so remember this is stage one so rip
points to the next instruction
so that next instruction is this
instruction and that's where we're
telling the read sys call to start
putting the bytes at that it's reading
in so effectively we are overwriting
these uh presumably i guess this is
a lot of bytes hold on let's see um
okay so
so these nine bytes here so when we're
specifying
um
stage so when we're specifying rip right
i keep saying that we're pointing here
this is where the bytes for stage two
are gonna end up
um so these nine bytes here are going to
get clobbered by what's read in
so that means i mean i i sent it 16
knobs to deal with that not have to do
this process of figuring how many bytes
it is not it's that difficult but
uh you really only need to send nine
knobs in order to account for the fact
that this is where we're
overwriting initially um
uh let's see here
all right so can execute e run
executables from the current directory i
thought it requires the full path
yeah so it just follows the standard
um i guess linux path conventions where
it
it can support relative paths um or
relative to your current working
directory you don't have to give it an
absolute path um
directory yeah okay yep
any hints on removing null bytes i've
used the
xor to zero out registers and i've been
using
push seems to push null bytes as well
uh okay i see what you're saying uh
so i've been using push seems to push
null bytes as well
so you're probably talking about um if i
do
pawn asm uh push
one two three four um
we will see that this
has no bytes in it right um
actually
into our three oh three four is uh
let's ask e4 right um so yeah it will
end up with these null bytes
um you have uh various
options for dealing with that um
let's see here so one
option is to um
use a register um so
move rax obviously this isn't going to
work you're still going to have uh
bytes but if instead you do some sort of
like let's say 0 1 0 1 here at the end
so now we don't have null bytes
but we can also now xor rax with
zero zero zero zero
zero one zero one and effectively what
that's going to
oh of course now we have zero zeros uh
we can xor
rax with
um
so we could let's see here
i mean there's various things i'm
probably going to show you something
that's not exactly right but this is
along the right idea
um
let's see here
okay actually no no let's uh stick with
that initial idea we'll just uh correct
it
so if we wanted um one two three four
uh to appear instead what we can do is
make it one three
three five uh it's
probably correct i think yeah because
now we're setting the least significant
bit
and then x or r ax rex or rax with
uh this and that will basically correct
it to one two three four
just doing uh xor operation so there's i
mean there's a number of ways to do it
um but this would be for instance one
way to start avoiding
old bytes and then obviously if you
wanted this to be on the stack you push
that to the stack
um there's also something to i guess
realize also is that when i execute
baby shell level one you'll see that i
included this uh leading slash to make
it an absolute path
as it turns out linux doesn't care how
many slashes you use
like this is the same thing so if you
have a specific number of bytes and it's
related to a path for instance
and you have some null bytes in there
that you're pushing this path to the
stack or whatever
an option is just include more
flashes okay
let's see here um
are there i don't see any current
questions does anyone have any questions
in our twitch
yeah sure
mhm
um when you're piping your shell code
okay i think i think i understand your
question um
so you're talking about uh like this for
instance how does
the label um
effectively work right okay so
if we assemble this we're going to get
these bytes
if we remove the label uh just because
it's the next instruction we can just
use rip
um you're gonna see that we get the
exact same bytes
so labels aren't actually um
in the bytes of your shell code it's the
the assembler takes care of doing this
so when we do this
rap plus my label the assembler when it
goes through to
create these raw uh bytes does math for
you to figure out
uh how far away my label is and just
kind of substitutes that directly and
you could think of it as
so it's not actually in the shell code
it's uh
it's dealt with by the the functionality
that's doing the assembling
yeah so um not actually entire
there's you could reference the label
directly
the reason that i'm doing rip plus my
label is the
so that it becomes uh rip relative
um because you could think that
um when you're creating some assembly
and you have a label this label could be
like very specifically
at the address hex 1000. um so you might
want
rax to now take on the value of hex 1000
um but you might not want that you might
want whatever this
label is to be relative to the
instruction pointer
and in the case of making the shell code
um basically not care about its
current ad like absolute address and
memory uh it's kind of nice just to do
things
all relative to the current value of the
instruction point
um so that's why we it's kind of like a
syntactic thing more than anything that
you say
rip plus my label just basically means i
want my label represented rip relative
yep
well from outside of asu get any cert
for completion of course
uh maybe oh no well
i'll ask you on sounds sounds nice
sounds like a
thing um
[Music]
it's the same technique to handle the
old bytes
from load effective address
um
[Music]
so
let's see here
so something how do we do this
i think it should be possible to make
your rip relative
address um
not use so many bytes uh because you
should be able to go
um
here it's possible let's see here if
loading it into eax will just lower the
number of bytes
i assume like al that doesn't even make
sense does it
um that doesn't make sense
it's definitely possible um
the question is how do we convince it so
if you like look up the
actual instructions you can do like one
byte and two byte
relative addressing um i just don't know
exactly what the syntax is here
in intel assembly rather than just
writing out the raw bytes by hand
um is it possible that it's like
light pointer or something oh
wait but did that change anything pretty
sure that didn't change anything
it's like the exact same right
assume like fights just gonna complain
yeah it doesn't change anything either
um there is definitely does anyone
twitch chat or zoom know how to do
like one bite-offs
let me take a look
so let me see what happens if i assume
the same thing will happen without a
label but let's just verify
i did like that
i might have to look after office hours
to figure out exactly what the syntax is
isn't it because rip is always a 64-bit
register yes it is always a 64-bit
register
but you can imagine um that we don't
need a full 64 bits to represent how far
away we want to move
rip it's possible right that you could
have an instruction that just allows you
to go plus or minus
um the value plus or minus 128
away from rip and just use one byte to
encode that
and it is possible to do that um
if you look up uh like
assembly related so for instance
actually maybe it's just like
jumps that that's gotta be more though
let's see here
for instance if i do jump my label
is that the right syntax yeah
okay so you can see that jump my label
plus two
uses way less bytes right it's just
actually using
eb to encode for the jump part and zero
two to encode for but i want to go rip
relative
plus uh hex to and then obviously this
hex 90 is the knob
um maybe i'm not sure that you can do it
with effective address
it i'm not entirely sure
so in this case is jump and lea
equivalent no
because we can imagine that the reason
we're doing a load effective
address is to prime a read syscall
to know where we want to be
reading our bytes in in this two-stage
shell code
so jump will literally jump to my label
plus two whereas load effective address
is just taking in that value
um let's see here
can we put ink byte pointer
in the text section
okay so this question of when we have a
restriction on a byte value
could we go over how to resolve this
case um just look at this video
after it's done it'll be on youtube and
also be on twitch that's
i think the very first thing that we
cover once you get through
me not knowing how to use twitch or zoom
my mic starts eventually working
um maybe load only the bytes we need
from rap to another register
and use that register not sure though oh
yeah that's an interesting idea let's
see here
[Music]
so if we for instance just load in rip
and it still is a
lot
um
yeah i not entirely sure there's there's
got to be a way to get the value of rap
usable without no bites i just don't
know off the top of my head
um oh eax
uh maybe
oh that's interesting it's the exact
same uh
assembly
actually what about eip and that'll save
some bytes
probably doesn't even save bytes there
i have no idea um
oh i guess it added a g though i don't
know what's going on
um
let's see here if anyone has more
questions feel free to ask otherwise i
can figure this
out after office hours and try to
respond
just push for some reason it's not
letting us push rip
i kind of sworn you could push all right
but
planes
okay quickly push rip to stack
i'd be very surprised that you can't do
oh yeah you could call
that's a good point all
dollar sign uh shorthand for rip yes
that's what this is
pop rax
this
happened there we're going to call and
execute this
good enough
i don't that's probably i would assume
that in this
actually it's uh rather than use dollar
signs for rip
oh what
so that adds null bytes
this dollar signed specifically in the
assembly or when the assembler goes
through it point to this current
instruction
as the current the actual current
instruction okay
but then when we do dollar sign plus
five oh and it's probably all these ffs
fbs because it's doing a negative when
it tries to resolve this
yeah i'm not entirely sure
there's
who was it that had the question about
uh not having bytes with uh
lea
what was your could you say your
question again i guess it's in
zoom
oh i guess i can scroll up can we use
the same techniques to handle the null
bytes from lea
um so i don't know i guess off the top
of my head
something to realize though is obviously
this isn't a super satisfying
answer is that you don't need this lea
stuff to make your shell code work
without null bytes there are other
ideas so presumably you'd want to be the
probably what's going through your mind
is that you want to use lea in order to
load the address of like bin sh or
slash flag or whatever
into a register that's embedded in your
shell code so for instance um
my label
rax or ap
plus so you're trying to probably do
something like this
where instead of a knob it would be like
a slash flag or
bin sh or whatever um but instead of
doing that you could just
not have this encoded or like not just
have these
raw bytes just sitting in the assembly
that you're going to try to reference to
obviously i mean
i don't know how to do that because i
don't know how to get this lea to work
without null bytes
um instead though similar to when we
were showing the
what's push that would have been zero
or zero x one yeah so similar to when we
were doing this technique which is kind
of what prompted that question
is you could do something like this
rather than have the raw bytes there and
then push this to the stack and
um pop so for instance if i
uh i lost it two x one three okay so if
i was interested in getting
one um one two three four which is what
this is after it decodes
um and then i could push uh
rax to the stack and then i can push
um rsp or we don't have to push rsp at
this point we can move
um say we wanted a reference
to this value to be in like
we want the address of this value to be
in
uh rbx um at this point now we can just
move
rsp into rbx um so what we're doing here
is that we're
taking one two three four in this case
it's encoded where the least significant
bit
is of each byte we tack on an extra one
and then we xor that away
so once this these two things go through
it'll be 0x1234
we push that to the stack and now the
stack pointer is currently pointing at
that so we want
um to just take that address put it into
rbx
now we have a reference to one two three
four
um in memory hopefully that's kind of
helping you get around this uh load
effective address
issue um
because i'm not exactly sure how you'd
use float effective address without
having those null bytes
get this functionality using the program
state before your shell code is executed
um i guess i don't exactly know what
that's referencing uh it's possible
though
i probably can't scroll to it can we
well maybe we can
yeah so before our shell code executes
it's possible that
i guess this is where we're executing
uh you can see here yeah so we are
executing here
you can see that rdx contains
the address of where the shell code
begins
at the very start so theoretically if
you really wanted to have those raw
bytes just sitting in memory you could
go
at an offset of rdx and
do the math in order to figure out
exactly where your bytes are sitting and
that would be another way to do it
but that might be a little more tricky
to reason about
those pawn tools automatically extract
the text
section so instead of having elf and raw
files we can just compile using tone
tools to get the raw bites
uh yeah so
this is the cool hip way of getting your
raw bites
of course yawn likes to show you the
underlying
principles going um and it's definitely
useful to understand those underlying
principles
of uh basically having an elf and being
able to object copy out a section
um i believe pawn tools is actually just
doing that under the hood so if i
make it crash let's see
um you'll see that it is
okay i guess it's using it's using a
slightly different process
it's taking our assembly and actually
using the assembler
and dumping that somewhere so whereas
yawn is using gcc
to produce an elf and then using object
copy
to copy the bytes out of the text
section
which of course works pawn tools under
the hood is using
assembler to do this um
which i guess is some ways a more
reasonable way of doing it seeing as
why would you use gcc and object copy
instead of the assembler to
assembling but it doesn't really matter
um
there's lots of ways to do the same
thing but yeah
um i think palm tools is a very
convenient way to do it especially if
you're gonna start scripting some of
your solutions
which uh as the class goes on scripting
will become
increasingly more useful to you if you
think about it from the perspective if
your current workflow is uh basically
creating these shell code or creating
these dot s
files with a bunch of assembly and
they're just like all over the place in
your home directory and then you're
running
gcc and then you're doing obj copy and
you're moving this to this file and this
to this file
instead you could just have it all
streamlined in one python file that just
does everything
and then i realize i have a bug oops i
accidentally included this just delete
that
rerun the python script everything just
happens i don't know i think it's a
bit of an easier workflow but there's
lots of benefits to
understanding john's process from like a
understanding some of the tooling going
on
are there any more questions could you
use
shift left and increment instructions to
get around not having
all bytes yeah definitely um not for
load effect at least not off the top of
my head for load effective address
so
this obviously happens like this so
yeah like theoretically my label could
be like
super far away but we're not our shell
code size is limited
or that we're not gonna be able to fix
that
well now let me think again
i mean you could do something insane
ish we do plus
that works um
so plus
need lots of this though
okay i guess you could do something
slightly insane
it's not that insane but
you could do something like this so that
now we've got
these yeah it's actually a pretty
reasonable solution actually for
solving this null byte issue um or we
just arbitrarily tack this on
and then could
like sub rax
0x one zero one zero zero one
no no by tonight yeah so i'm not this
might be slightly off but something
along these lines yeah i guess would be
a solution to the
whole bite lea problem um
yeah i if something feels like there
might be something
wrong with this approach maybe there's
not i don't know
you definitely have to account for the
fact that this oh
i don't know it seems like this could
work but there might be some debugging
required to figure that out
my uh my opinion this is a slightly more
complicated way
that's what i was trying oh well
couldn't get it to work though yeah it's
i think this would work in theory but
this might be slightly off
um answer my question i had to go do you
think a
hot dog is a sandwich
uh
no definitely not uh can you explain
more about interacting with processes
using
yeah so first thing you got to do is
import pwn
um and then tone dot
this is useful for when we're using
pwn.asm
but not necessarily for processes might
not matter
um this you just specify for the first
argument the path to the binary
um and then it shows you that they've
started this local process
it's running with this process id maybe
that's useful to you
um and then there's tons of features but
the the basic ones that you need to know
how to use or that are extremely useful
are proc.read
so we can see now we just read out that
introduction
and proc.rights so if i for instance
write
cc which is our int 3 instruction
um and then i proc read 4096 again
about 4096 is kind of arbitrary speed up
to 40 96 bytes
um we'll see that this interior
instruction came back to us so yeah
hopefully then i would recommend
googling palm tools there's um
all sorts of very interesting uh things
you can do so for instance like you can
read until
something happens and you can um
there's all sorts like another thing you
could actually do let me
show because this is maybe the next most
useful thing
oftentimes uh is that you can do
pawn.interactive
or proc.interactive and it just kind of
makes the program interactive now so if
i just
i don't know why this isn't working i
don't know but
it normally works maybe it's because
we're my python or i'm not sure
how would you set argv in a executive
um so in general
i won't because it's more work but it
can be done of course
um so if we
wanted to um
set up argv basically what's going to
need to happen
is that so rgv is going to be a
pointer to a pointer to that but
at the end of that is our our data um
so let's see here i want to go through
let's say all right let's let's show
writing uh
bin sh dash p why not um
so first thing we need to do is
cis exec ve so move
rax 59 um
and then we want our file name um
so let's just push uh
let's go with hold on
how should we do this i will be insane
and use f strings why not
uh maybe not
hold on let's let that error out
uh so we want ultimately um
oh actually this pawn another
interesting thing or useful thing that
palm tools has
is a p32 and p64
i
oh it's definitely
should we want an sh anyways
hold on i might remember how to do this
where is it
oh maybe it's because it's not a very i
should probably listen to it
does that fix it okay it does all right
that makes way more sense
um okay so
basically what this does is it'll little
nd and encode our bin sh string
so we can see at the end is this 2f2f
which is our leading slashes and
somewhere in here is another 2f
um okay so
what we might want to do actually let's
make this slightly easier and just put
an old bite at the end
that's not going to show up but whatever
um okay so palm
dot assemble um
so if we wanted to push nsh to the stack
okay let's make sure it doesn't complain
it does complain we need to move that
into rax because if you're gonna push a
litter
or uh immediate it has to be four bytes
it doesn't eight bytes
um so if we push rax okay so now we're
pushing
rax to the stack um or pushing
bin sh to the stack uh and then
um so
actually
instead of using rx let's uh let's set
this up so we want 59
to be in rax so let's
use rcx here whatever
um so the next thing that we need to
do is make rdi be a path to our binary
so if we move rdi
rsp now rsp
so rsp is going to be the current
location of our stack which is
at the top of our stack is currently
pointing to that bin sh
um so we move rsp into
rdi uh in order to have a pointer to
that string
um so the next thing though that we need
is
here we need
rsi to contain a pointer to a pointer so
the first thing
that you might think to do is to push
rsp
and then move rsi rsp
so by pushing rsp we said that this is
currently a pointer to bin sh so if we
push a pointer to that pointer
or if we make it so the rsp is now a
pointer to that pointer we have our
pointer to a pointer to bin sh
um but we also need a null on the stack
because the
list it's basically a pointer to a
pointer for reading out all of these
args
where the last one needs to be
null so that means we need to push a
zero to the stack
um and then we can still just make rdx0
because
we're not going to set up the
environment so move
rdx0 oops that's
not right there okay um
then i think in theory this would work
uh but let's say we also want to
put our dash p there um
because say we want to call bin sh with
that dash p flag since that's a
useful thing to do um actually let me
[Music]
zero uh we'll say hex
72d
um so we pushed the
zero here okay so the next thing so this
is our last thing
um so now we want to move rcx
d0x70 to d
and then we want to push rcx to the
stack
um yeah because then we will have okay
so now what's going to be on the stack
is oh this isn't quite the right order
is it
why does this feel
x
okay so i think
so we push okay so this is bin sh we
push bin sh to the stack
and then put dash
p into rcx and we push that to the stack
okay i see this rdi
rdi rsp thing
needs to happen after we push
because we need rsp every time we do a
push rsp is moving around and we need
specifically
a pointer to bin sh um
and then
set this so rdi contains that pointer
and we move rc 0 x
7d to d into rcx we push rcx
to stack and then we
push rsp stack
okay so this is where okay so this is
where we need to
okay so currently the stack contains our
raw data so it contains bin sh it
contains dash p
so the next thing we want to put on the
stack is pointers to these things
so we want to push 0 onto the stack
which will be a null pointer because
that's going to be the very last
pointer that basically ends our list of
arg v
um and then we want to push
uh actually where is this rcx
so let's quickly take a
um so this contains uh
rdi contains the rsp pointing there
but we also need to get a reference to
the next thing so let's say that our
uh bx if that one doesn't matter
rbx does not matter okay so let's make
our bx contain
rsp now so now we have in rdi is sitting
a pointer to bin sh
in rbx is setting a pointer to dash
p so now what we're going to do
is that we are going to push uh so we
end the list with 0
and then we want to push rbx
and then we want to push rdi
and then we want rsi which is our arg
v thing to contain rsp so now we have a
pointer
that points to here and then the next
pointer is going to here be here and
then it's going to be a null pointer
so rdi is pointing to this
rbx is pointing uh did i say rbx that
should be rcx
oh no no we moved rsp to rbx okay
our bx is pointing to here and then zero
is our null thing okay
so now we have been sh-p we null out the
environment
and then we call syscall i think that
logic sounds right i really hope it is
um and then let's
just do
all this our shell code write to a file
just so we can s
trace
gel code and then with
open
f dot write shell code
okay and if we baby trace
with our shell code
i forget to change rex to 59
i just oh wait we were started a new
process didn't we
executing exec v e bin sh okay beautiful
all right we did exactly right one shot
at boom all right that's awesome
okay so now if we run it without s trace
to make it actually work
um and let's cat shellcode dash
boom uh ls who am i
cat flag boom all right bin sh dash p
that is how you would set up
rgv on stack
obviously it takes a little bit of
thinking about it but if you make a
mistake you can use gdb
is there a smooth way of using gdb with
phone tools yes there is
uh in fact i have uh
what is that thing called
actually hold on let me check my email i
have
something that shows how to use it
is this it
i think this is it okay let me post it
in twitch i will post it
soon that is a it kind of demonstrates a
way to use gdb with pawn tools and maybe
in a future office hour so i can show
that off
is there any uh final questions i'm
going to start wrapping up this office
hours
not this is outrageous that man a hot
dog
is not a sandwich obviously
that answered the exact fee question
that answers that
okay is there any final questions
all right well thank you for uh joining
me for my office hours um
tomorrow we will have a stream again the
the normal stream at 2 30 arizona time
um we will play yawn's
videos for baby jail
and then at 4 30 the normal class will
start
all right see you guys let's see how to
end everything that's
and eventually i'll figure out how to
end obs
stop streaming awesome