VxWorks操作系统复位实战(二)[by Progsoft]

时间:2022-03-28 04:01:04

引子程序解释

如果你已经*printf系列的溢出漏洞问题,你将轻松发现问题所在,同时也可以跳过本文:)。

该程序存在两个问题:

一、taskName定义是8字节字符串,但全局变量初始化为11个字节。

二、Buffer字符串输出直接使用printf,而不是printf("%s",Buffer)。

关于问题一要说明的是在VC下编译器会很严格的检查越界并提示“error C2117: 'TASK01_SUB' : array bounds overflow”数组越界,导致编译都无法完成,但其他不严格编译器则只会产生Info 或 Warning告警而已。

那么在非严格编译器得出的代码是怎么样的呢?

非常不幸的是 编译器简单的使用了去尾法。

|        TaskName       |   tcbCnt  |
 54 41 53 4B 30 31 5F 53 00 00 00 00

taskName是没有结束符号0的,什么时候结束完全受限于tcbCnt或更后面的字符。

这样当sprintf(Buffer, "%s run time :%d ", TaskCB[k].taskName, TaskCB[k].tcbCnt); 执行过后。Buffer的值是多少?答案未知。

我们可以假设tcbCnt一旦为0x6e25,那么Buffer将等于"TASK01_S%n"。

配合printf(Buuffer);结果就是printf("TASK01_S%n");

这个就是导致复位的罪魁祸首。输出字符串有格式化的%n,但是后面竟然没有参数。

在PowerPC系列函数调用都是采用寄存器传值。

所以在调用函数printf之前,这时的r3肯定是Buffer的首地址,但r4/r5/r6...呢?那就是随即值了。

大家都知道%n的作用,就是将当前格式化字符串长度写入某个地址,这时r4是随机值,天知道写到哪个地址了。

因为产生的%n是随即写地址,写并不代表一定复位。

所以开始祈祷吧,一个随机的复位幽灵诞生了。

由于无PowerPC环境,所以修改了一个Windows+VC的程序当做实例,有兴趣可以看下了。

VxWorks操作系统复位实战(二)[by Progsoft]#include <stdio.h>
VxWorks操作系统复位实战(二)[by Progsoft]
#define UINT8    unsigned char
VxWorks操作系统复位实战(二)[by Progsoft]
#define UINT32   unsigned long
VxWorks操作系统复位实战(二)[by Progsoft]
#define MAX_TASK 6
VxWorks操作系统复位实战(二)[by Progsoft]
VxWorks操作系统复位实战(二)[by Progsoft]typedef 
struct  tcb
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]
...
{
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]    
char      taskName[8]; /**//* 任务名称 */

VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]    UINT32    tcbCnt;      
/**//* 任务运行时间 */
VxWorks操作系统复位实战(二)[by Progsoft]}
 TCB; 
VxWorks操作系统复位实战(二)[by Progsoft]
VxWorks操作系统复位实战(二)[by Progsoft]TCB TaskCB[MAX_TASK] 
=
 
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]
...

VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]    
...{"TASK00_",  0x00006e25}
,
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]    
...{"TASK01_",  0x00007025}
,
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]    
...{"TASK02_",  0x00006425}
,
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]    
...{"TASK03_",  0x00007825}
,
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]    
...{"TASK04_",  0x00007325}
,
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]    
...{"TASK05_",  0x00006325}
,
VxWorks操作系统复位实战(二)[by Progsoft]}

VxWorks操作系统复位实战(二)[by Progsoft]
VxWorks操作系统复位实战(二)[by Progsoft]
void
 Task_Root()
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]
...
{
VxWorks操作系统复位实战(二)[by Progsoft]    
char   Buffer[256
];
VxWorks操作系统复位实战(二)[by Progsoft]    UINT8  k;
VxWorks操作系统复位实战(二)[by Progsoft]    UINT32 Backup;
VxWorks操作系统复位实战(二)[by Progsoft]
VxWorks操作系统复位实战(二)[by Progsoft]    
for (k = 0; k < MAX_TASK; k++
)
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]    
...
{
VxWorks操作系统复位实战(二)[by Progsoft]        sprintf(Buffer, 
"%s run time :%d "
, TaskCB[k].taskName, TaskCB[k].tcbCnt); 
VxWorks操作系统复位实战(二)[by Progsoft]        Backup 
= *(UINT32 *
)Buffer;
VxWorks操作系统复位实战(二)[by Progsoft]        printf(Buffer); 
VxWorks操作系统复位实战(二)[by Progsoft]        printf(
"Before printf:%#.8x, After printf:%#.8x ", Backup, *(UINT32 *
)Buffer);
VxWorks操作系统复位实战(二)[by Progsoft]    }

VxWorks操作系统复位实战(二)[by Progsoft]}

VxWorks操作系统复位实战(二)[by Progsoft]
VxWorks操作系统复位实战(二)[by Progsoft]
void  Init_TaskCB()
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]
...
{
VxWorks操作系统复位实战(二)[by Progsoft]    UINT8 k;
VxWorks操作系统复位实战(二)[by Progsoft]    
for (k = 0; k< MAX_TASK; k++
)
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]    
...
{
VxWorks操作系统复位实战(二)[by Progsoft]        TaskCB[k].taskName[
7= 'S'
;
VxWorks操作系统复位实战(二)[by Progsoft]    }

VxWorks操作系统复位实战(二)[by Progsoft]}

VxWorks操作系统复位实战(二)[by Progsoft]
VxWorks操作系统复位实战(二)[by Progsoft]
void  main()
VxWorks操作系统复位实战(二)[by Progsoft]VxWorks操作系统复位实战(二)[by Progsoft]
...
{
VxWorks操作系统复位实战(二)[by Progsoft]    Init_TaskCB();
VxWorks操作系统复位实战(二)[by Progsoft]    Task_Root();
VxWorks操作系统复位实战(二)[by Progsoft]}

注:该复位问题来源于工作中的一个实例,号称“复位幽灵”。由于出现条件琢磨不定,时而一天一次,时而半个月,但只要当你放松警惕,以为没问题的时候,它必定又冒出来。最后历时4个月将其攻克。所以一个安全的代码是多么重要,否则就等着被这等低级BUG戏弄吧,^_^。