首页
社区
课程
招聘
[原创]看我攻破所谓的“安全系统”
发表于: 2021-7-15 16:37 15556

[原创]看我攻破所谓的“安全系统”

2021-7-15 16:37
15556

在前段时间,因为闲着无聊,我注意到看雪上有个“成功登陆文件系统,并取到文件”的挑战,奖金高达50块钱。如下所示:
图片描述
一共3个系列,难度逐渐提高,题目的套路是给一个Linux虚拟机文件,你不知道root密码,让你获取到root下的文件。下面开始介绍我使用的分析方法。
图片描述

因为是虚拟机文件,我最开始直接在另一台Kali挂载了题目中的VMDK虚拟磁盘文件,可以读取硬盘中的内容:
该硬盘分区和传统的Linux差不多,它一共有两个分区,启动分区和存放根文件系统的分区,启动分区是没加密的,而存放着root文件夹的另一个分区被LUKS保护着。
启动分区存放着GURB,Linux内核,initramfs。
图片描述
LUKS保护分区:
图片描述
很明显的是,LUKS解密的逻辑肯定是放在启动分区的initramfs中。不幸的是,该文件系统被加密了:
图片描述
但是Linux kernel没被加密:
图片描述

根据本人的分析经验,加解密文件系统的算法一般是放在Linux内核中,使用IDA直接分析populate_rootfs
图片描述
好了直接调用这个SerpentDecrypt函数直接解密该文件系统,当然可以使用QEMU直接调试打断点然后DUMP出明文数据也可以,但是搭建环境需要时间,最快的方法直接使用现成的函数,unicorn模拟执行即可:

解开文件系统后,可以看到LUKS加密密钥生成的逻辑(再后面的题目中还魔改了LUKS加密引擎)。到这里可以说是基本获取到权限,我们可以修改文件系统,插入代码,反弹shell回来之类的方法获取到权限。
图片描述
图片描述

有没有更快的方法?如果我能直接读写虚拟机内存,将判断登陆的二进制代码直接强制让它进入登陆成功的流程,那我不是可以无视加密直接登陆进系统?是的,虚拟机允许修改guest机的内存,无论是跨进程读写vmx进程或者修改vmem文件的方法都能读写虚拟机实例的内存。
先调小虚拟机内存,方便定位:
图片描述

随便找个x64的login程序,找到特征码:
图片描述
挂起虚拟机,虚拟机目录下生成对应的内存文件:
图片描述
通过特征码定位到判断点
图片描述
图片描述

恢复快照,输入错误的密码,也可直接进入系统:
图片描述
成功获取到文件:
图片描述

一共三个系列,方法都大同小异:
图片描述

类似的挑战还是颇具现实意义,例如一些设备,就是使用这类加密,但是设备不容易修改内存,通过纯逆向的方法也可以进行分析。下面简单总结下分析方法:
1.纯逆向工程,分析Linux内核。内核加密就分析GRUB。解开文件系统,重新打包获取权限。
2.直接修改内核或者grub文件,插入shellcode,获取权限。
3.直接修改内存,插入shellcode,或者修改跳转,获取权限。
4.进入单用户模式,但是有可能开发者会防止你进入单用户模式移除一些代码。

from unicorn import *
from capstone import *
from unicorn.x86_const import *
from elftools.elf.elffile import ELFFile
from elftools.elf.segments import Segment
import ctypes
import binascii
import hexdump
import struct
filepath='kernel.elf'
 
load_base=0xFFFFFFFF81000000
stack_base=0
stack_size=0x20000
var_base=stack_base+stack_size
var_size=0x2000000
stop_stub_addr=var_base+var_size
stop_stub_size=0x10000
 
 
emu = Uc(UC_ARCH_X86, UC_MODE_64)
 
def disasm(bytecode,addr):
    md=Cs(CS_ARCH_X86,UC_MODE_64)
    for asm in md.disasm(bytecode,addr):
        return '%s\t%s'%(asm.mnemonic,asm.op_str)
def align(addr, size, growl):
    UC_MEM_ALIGN = 0x1000
    to = ctypes.c_uint64(UC_MEM_ALIGN).value
    mask = ctypes.c_uint64(0xFFFFFFFFFFFFFFFF).value ^ ctypes.c_uint64(to - 1).value
    right = addr + size
    right = (right + to - 1) & mask
    addr &= mask
    size = right - addr
    if growl:
        size = (size + to - 1) & mask
    return addr, size
def hook_code(uc, address, size, user_data):
    #bytecode=emu.mem_read(address,size)
    #print(" 0x%x :%s"%(address,disasm(bytecode,address)))
    if address==stop_stub_addr:
        emu.emu_stop()
 
 
#init var
def init_emu():
    with open(filepath, 'rb') as elffile:
        elf=ELFFile(elffile)
        load_segments_addr=[0xFFFFFFFF81000000,0xFFFFFFFF815EE000]
        load_segments = [x for x in elf.iter_segments() if x.header.p_type == 'PT_LOAD']
 
        for segment in load_segments:
 
            prot = UC_PROT_ALL
 
            if segment.header.p_vaddr not in load_segments_addr:
                continue
            print('mem_map: addr=0x%x  size=0x%x'%(segment.header.p_vaddr,segment.header.p_memsz))
            addr,size=align(load_base + segment.header.p_vaddr,segment.header.p_memsz,True)
            addr=segment.header.p_vaddr
            print('fix_mem_map: addr=0x%x  size=0x%x'%(addr,size))
            emu.mem_map(addr, size, prot)
            emu.mem_write(addr, segment.data())
 
    emu.mem_map(stack_base, stack_size, UC_PROT_ALL)
    emu.mem_map(var_base, var_size, UC_PROT_ALL)
    emu.mem_map(stop_stub_addr, stop_stub_size, UC_PROT_ALL)
 
def SerpentDecrypt(data):
 
 
    emu.mem_write(stack_base+stack_size-8, struct.pack('Q',stop_stub_addr))
    emu.mem_write(var_base, data)
 
 
    SerpentDecrypt_addr=0xFFFFFFFF81004660
 
 
    #SerpentDecrypt
    code=emu.mem_read(SerpentDecrypt_addr, 8)
    hexdump.hexdump(code)
    emu.reg_write(UC_X86_REG_RSP, stack_base+stack_size-8)
    emu.reg_write(UC_X86_REG_RDI, var_base)
    emu.reg_write(UC_X86_REG_RSI, len(data))
    #emu.reg_write(UC_MIPS_REG_RA,stop_stub_addr)
    #emu.reg_write(UC_MIPS_REG_SP,stack_base+stack_size)
    emu.hook_add(UC_HOOK_CODE, hook_code,begin=stop_stub_addr, end=stop_stub_addr+stop_stub_size)
    emu.emu_start(SerpentDecrypt_addr, SerpentDecrypt_addr + 0x1000)
    return emu.mem_read(var_base,len(data))
 
 
if __name__=="__main__":
    with open('initramfs.img','rb') as fd:
        data=fd.read()
    print('%x'%len(data))
    init_emu()
    dec_data=SerpentDecrypt(data)
    #dec_data=SerpentDecrypt(bytes(dec_data))[0:32]
 
    #hexdump.hexdump(dec_data)
    with open('initramfs.gzip','wb+') as fd:
        fd.write(dec_data)
from unicorn import *
from capstone import *
from unicorn.x86_const import *
from elftools.elf.elffile import ELFFile
from elftools.elf.segments import Segment
import ctypes
import binascii
import hexdump
import struct
filepath='kernel.elf'
 
load_base=0xFFFFFFFF81000000
stack_base=0
stack_size=0x20000
var_base=stack_base+stack_size
var_size=0x2000000
stop_stub_addr=var_base+var_size
stop_stub_size=0x10000
 
 
emu = Uc(UC_ARCH_X86, UC_MODE_64)
 
def disasm(bytecode,addr):
    md=Cs(CS_ARCH_X86,UC_MODE_64)
    for asm in md.disasm(bytecode,addr):
        return '%s\t%s'%(asm.mnemonic,asm.op_str)
def align(addr, size, growl):
    UC_MEM_ALIGN = 0x1000
    to = ctypes.c_uint64(UC_MEM_ALIGN).value
    mask = ctypes.c_uint64(0xFFFFFFFFFFFFFFFF).value ^ ctypes.c_uint64(to - 1).value
    right = addr + size
    right = (right + to - 1) & mask
    addr &= mask
    size = right - addr
    if growl:
        size = (size + to - 1) & mask
    return addr, size
def hook_code(uc, address, size, user_data):
    #bytecode=emu.mem_read(address,size)
    #print(" 0x%x :%s"%(address,disasm(bytecode,address)))
    if address==stop_stub_addr:
        emu.emu_stop()
 
 
#init var
def init_emu():
    with open(filepath, 'rb') as elffile:
        elf=ELFFile(elffile)

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-7-15 17:30 被wmsuper编辑 ,原因:
收藏
免费 16
支持
分享
最新回复 (22)
雪    币: 3161
活跃值: (5141)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
2
wmsuper yyds
2021-7-15 16:40
0
雪    币: 889
活跃值: (4118)
能力值: ( LV6,RANK:98 )
在线值:
发帖
回帖
粉丝
3
wmsuper yyds
2021-7-15 16:45
0
雪    币: 5182
活跃值: (9697)
能力值: ( LV9,RANK:181 )
在线值:
发帖
回帖
粉丝
4
666,这种保护方式有一些安全产品也是一直这么用的!
2021-7-15 16:46
0
雪    币: 1631
活跃值: (1364)
能力值: ( LV7,RANK:117 )
在线值:
发帖
回帖
粉丝
5
wmsuper yyds
2021-7-15 16:48
0
雪    币: 2040
活跃值: (4950)
能力值: ( LV13,RANK:278 )
在线值:
发帖
回帖
粉丝
6
wmsuper yyds
2021-7-15 16:53
0
雪    币: 164
活跃值: (1823)
能力值: ( LV11,RANK:185 )
在线值:
发帖
回帖
粉丝
7
star
2021-7-15 16:56
0
雪    币: 14517
活跃值: (17538)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
8
晴天师傅闲着无聊顺手破解了个加密的操作系统;而我闲着无聊就只能看着大佬操作并大喊”666“
2021-7-15 17:01
0
雪    币: 2827
活跃值: (2628)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
9
wmsuper yyds
2021-7-15 17:29
0
雪    币: 35
活跃值: (5254)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
wsc
10
wmsuper yyds 
2021-7-15 17:29
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
https://bbs.pediy.com/thread-268082-1.htm
下载没了,谁能帮忙?
多谢
2021-7-15 17:41
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
https://bbs.pediy.com/thread-268082-1.htm
下载没了,谁能帮忙?
多谢
2021-7-15 17:41
0
雪    币: 10868
活跃值: (14664)
能力值: ( LV13,RANK:400 )
在线值:
发帖
回帖
粉丝
13
evandrix https://bbs.pediy.com/thread-268082-1.htm 下载没了,谁能帮忙? 多谢
链接:https://pan.baidu.com/s/1FAu4IUVlkWN63x05RsTTGA 
提取码:3nxy
2021-7-15 17:45
0
雪    币: 7403
活跃值: (2034)
能力值: ( LV4,RANK:42 )
在线值:
发帖
回帖
粉丝
14
wmsuper yyds 
2021-7-15 19:28
0
雪    币: 2089
活跃值: (3933)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
很好很强大
2021-7-15 20:45
0
雪    币: 177
活跃值: (79)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
很好的思路,学习了!
2021-7-15 21:30
0
雪    币: 1293
活跃值: (109)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
17
wmsuper yyds
2021-8-3 09:39
0
雪    币: 914
活跃值: (2463)
能力值: ( LV5,RANK:68 )
在线值:
发帖
回帖
粉丝
18
好贴
2021-8-3 09:43
0
雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
很好的思路,长见识了。
2021-8-5 01:36
0
雪    币: 1022
活跃值: (292)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
都是玩概念,哪些专家园士,卧龙风爪除了炒炒名词,对社会没有啥实质贡献
2021-8-5 09:16
0
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
21
感谢分享!
2021-8-5 09:45
0
雪    币: 620
活跃值: (2021)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
tql
2021-8-5 15:59
0
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
efi启动文件,好破解吗?
2024-2-21 15:08
0
游客
登录 | 注册 方可回帖
返回
//