shelly
Category: Pwn
Description
sally sells seashells by the seashore sally sells seashells by the seashore sally sells seashells by the seashore sally sells seashells by the seashore sally sells seashells by the seashore sally sells seashells by the seashore sally sells seashells by the seashore sally sells seashells by the seashore
nc tjc.tf 31365
Attachments: chall
Write-up
This is the file
output of chall
:
Text Only | |
---|---|
And this is the checksec
output of chall
:
Text Only | |
---|---|
Let's analyze the program with Ghidra. The following snippet is the pseudocode generated for main()
:
After analyzing the provided code, we can identify a buffer called local_108
with a size of 256
bytes. The program first prints the address of the buffer, before it reads user input of up to 512
bytes and stores it in local_108
. This immediately reveals a stack overflow vulnerability.
Since the stack is executable (as indicated by NX disabled
in the checksec
output), we can inject our shellcode into the stack and return to the start of our shellcode. However, there is a check in the code that looks for the presence of the syscall
instruction:
Text Only | |
---|---|
Fortunately, we can bypass this check by supplying a null byte (0x00
) at the beginning of our input. The condition (510 < i) || (local_108[i] == '\0')
allows us to prematurely return and avoid the syscall
check. Since fgets
does not terminate in the presence of a null byte, we do not need to worry about prefixing our input with a null byte.
In summary, our input should consist of:
1. A 0x00
byte to trigger the premature return and bypass the syscall
check.
2. Our shellcode.
3. The remaining bytes needed to overwrite the saved rbp
and the return address.
The above input has been written as a pwntool script, which can be found here.
When running the script, we obtain our flag:
Flag: tjctf{s4lly_s3lls_s34sh3lls_50973fce}