VxWorks操作系统复位实战(二)[by Progsoft]
来源:百度文库 编辑:神马文学网 时间:2024/04/28 17:05:47
如果你已经*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 00taskName是没有结束符号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的程序当做实例,有兴趣可以看下了。#include
#define UINT8 unsigned char
#define UINT32 unsigned long
#define MAX_TASK 6typedef struct tcb
...{
char taskName[8]; /**//* 任务名称 */
UINT32 tcbCnt; /**//* 任务运行时间 */
} TCB; TCB TaskCB[MAX_TASK] =
...{
...{"TASK00_", 0x00006e25},
...{"TASK01_", 0x00007025},
...{"TASK02_", 0x00006425},
...{"TASK03_", 0x00007825},
...{"TASK04_", 0x00007325},
...{"TASK05_", 0x00006325},
}; void Task_Root()
...{
char Buffer[256];
UINT8 k;
UINT32 Backup; for (k = 0; k < MAX_TASK; k++)
...{
sprintf(Buffer, "%s run time :%d ", TaskCB[k].taskName, TaskCB[k].tcbCnt);
Backup = *(UINT32 *)Buffer;
printf(Buffer);
printf("Before printf:%#.8x, After printf:%#.8x ", Backup, *(UINT32 *)Buffer);
}
}void Init_TaskCB()
...{
UINT8 k;
for (k = 0; k< MAX_TASK; k++)
...{
TaskCB[k].taskName[7] = 'S';
}
}void main()
...{
Init_TaskCB();
Task_Root();
}
注:该复位问题来源于工作中的一个实例,号称“复位幽灵”。由于出现条件琢磨不定,时而一天一次,时而半个月,但只要当你放松警惕,以为没问题的时候,它必定又冒出来。最后历时4个月将其攻克。所以一个安全的代码是多么重要,否则就等着被这等低级BUG戏弄吧,^_^。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/progsoft/archive/2006/11/28/1417741.aspx
54 41 53 4B 30 31 5F 53 00 00 00 00taskName是没有结束符号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的程序当做实例,有兴趣可以看下了。#include
#define UINT8 unsigned char
#define UINT32 unsigned long
#define MAX_TASK 6typedef struct tcb
...{
char taskName[8]; /**//* 任务名称 */
UINT32 tcbCnt; /**//* 任务运行时间 */
} TCB; TCB TaskCB[MAX_TASK] =
...{
...{"TASK00_", 0x00006e25},
...{"TASK01_", 0x00007025},
...{"TASK02_", 0x00006425},
...{"TASK03_", 0x00007825},
...{"TASK04_", 0x00007325},
...{"TASK05_", 0x00006325},
}; void Task_Root()
...{
char Buffer[256];
UINT8 k;
UINT32 Backup; for (k = 0; k < MAX_TASK; k++)
...{
sprintf(Buffer, "%s run time :%d ", TaskCB[k].taskName, TaskCB[k].tcbCnt);
Backup = *(UINT32 *)Buffer;
printf(Buffer);
printf("Before printf:%#.8x, After printf:%#.8x ", Backup, *(UINT32 *)Buffer);
}
}void Init_TaskCB()
...{
UINT8 k;
for (k = 0; k< MAX_TASK; k++)
...{
TaskCB[k].taskName[7] = 'S';
}
}void main()
...{
Init_TaskCB();
Task_Root();
}
注:该复位问题来源于工作中的一个实例,号称“复位幽灵”。由于出现条件琢磨不定,时而一天一次,时而半个月,但只要当你放松警惕,以为没问题的时候,它必定又冒出来。最后历时4个月将其攻克。所以一个安全的代码是多么重要,否则就等着被这等低级BUG戏弄吧,^_^。 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/progsoft/archive/2006/11/28/1417741.aspx
VxWorks操作系统复位实战(二)[by Progsoft]
VxWorks操作系统复位实战(四)[by Progsoft]
嵌入式操作系统VxWorks简介
嵌入式实时操作系统VxWorks入门
嵌入式实时操作系统VxWorks入门vvvvvv
vxworks FAQ(中文)
管理实战内容(二)
筋长一寸 寿延十年:香港名医朱增祥拉筋复位法二
实战SVN For Apache2(二)
实战技巧:抓涨停板秘诀(二)
6s管理实战内容(二)
江城超子排列三实战方法简介(二)
KDJ指标的实战经验应用(二)
再论选股方法的成功率问题。(原创) - 实战交流 - 顶牛论坛 - Powered by ...
哲理故事集(二)- Powered by 博易-AnyP.cn
成本分析实战技法二
成本分析实战技法二
分时图实战图解二
奇门实战案例剖析二
vxWorks学习笔记
VxWorks基本概念及常见问题
建立vxworks调试环境
VxWorks中文FAQ
windows操作系统使用交流 - 注册表的专题 - powered by discuz!