git it, GOT it, good!
Overwriting GOT to get a shell.
3 min read
[ + ]Overview
Running the binary for the first time we see the following:
There is no address space layout randomization protections on the binary, which makes it possible for us to exploit the vulnerability found.
[ + ]Reversing
main
Here is the important chunk of the main
function.
We can see a few things from the section highlighted in yellow.
0x18
(24) bytes are read onto the stack usingfgets
- 8 bytes are moved into
rcx
fromrbp-8
->rbp-16
- 8 bytes are moved into
rax
fromrbp-24
->rbp-32
- 8 bytes are moved into
rdx
fromrbp-16
->rbp-24
- The value at the address of
rcx
is overwritten byrax
- The value at the address of
rcx+8
is overwritten byrdx
- 8 bytes are moved into
rax
fromrbp-24
->rbp-32
and used at the parameter toputs
Now that we have that layed out we can understand the vulnerability. We can overwrite the value at some address we specify by some value we specify. In this case we can opt to overwrite the global offset table (see tab got
), and more specifically puts
with the address of run_cmd
and pass the parameter of our choosing.
See the next section for more details.
run_cmd
Here we can see run_cmd
.
run_cmd
takes a single argument of 8 bytes and passes that as an argument to system
.
got
Here we can see the global offset table.
The global offset table is writeable, and since PIE is not enabled, it makes it easy for us to change the value at 0x601018
to overwrite the value of puts
.
[ + ]Exploiting
To exploit this vulnerability, we can pass 24 bytes into the input, such that we overwrite the puts
entry in the got
with that of run_cmd
and pass /bin/sh
as the argument to run_cmd
.
The input is as follows:
-------------------------------------------------------------------
| /bin/sh | run_cmd address | puts@got address |
-------------------------------------------------------------------
This will look as follows on the stack:
--------------------------
| /bin/sh |
--------------------------
| run_cmd address |
--------------------------
| puts@got address |
--------------------------
Causing puts@got
to be overwritten with run_cmd
and /bin/sh
to be the paramater of the "puts" call.
We can see this when debugging.
We can also see the got
being modified after running step by step:
Then when we get to the "puts" call, we see the following:
[ + ]Solution
Solver
from pwn import *
from pwnlib.util.packing import *
# Context
context.arch = 'amd64'
# context.log_level = 'DEBUG'
def pwn():
conn = process(['/tmp/lima/git_got_good'])
pause()
conn.recvuntil(b'Anyways, give me a string to save:')
# /bin/sh, run_cmd, _puts address - 8
# got writeable
conn.sendline(p64(0x68732F6E69622F) + p64(0x000000000040074B) + p64(0x0000000000601010))
conn.interactive()
if __name__ == "__main__":
pwn()