Exploiting over Sockets
File Descriptors and Sockets
File Descriptors are integers that represent conections to sockets or files or whatever you're connecting to. In Unix systems, there are
3main file descriptors (often abbreviated fd) for each application:
These are, as shown above, standard input, output and error. You've probably used them before yourself, for example to hide errors when running commands:
find / -name secret.txt 2>/dev/null
Here you're piping
/dev/null, which is the same principle.
Many binaries in CTFs use programs such as
stderr) to the user when they connect. These are super simple and often require no more than a replacement of
p = process()
With the line
p = remote(host, port)
Others, however, implement their own socket programming in C. In these scenarios,
stdoutmay not be shown back to the user.
The reason for this is every new connection has a different fd. If you listen in C, since fd 0-2 is reserved, the listening socket will often be assigned fd
3. Once we connect, we set up another fd, fd
4is certain, but statistically likely).
In these scenarios, it's just as simple to pop a shell. This shell, however, is not shown back to the user - it's shown back to the terminal running the server. Why? Because it utilises fd
2for its I/O.
Here we have to tell the program to duplicate the file descriptor in order to redirect
4, and glibc provides a simple way to do so.
dupsyscall (and C function) duplicates the fd and uses the lowest-numbered free fd. However, we need to ensure it's fd
4that's used, so we can use
dup2takes in two parameters: a
oldfdis duplicated to
newfd, allowing us to interact with
stdoutand actually use any shell we may have popped.