求救 socket 缓冲溢出问题

cqruan 2010-04-13 07:04:15
如果一个字符串实际的长度,超过了它能容纳的长度,那么就会造成缓冲溢出的问题。
比如:
char ch[10];

但是如果超过10个字符长度的字符串,赋值给ch时,就会发生缓冲溢出错误。而且攻击者会制造shell漏洞攻击来执行任意的代码;

结合下面的程序,请问socket的数据传送,如果防止这个问题呢?


typedef struct _tagPerson
{
char name[20];
char number[20];
}Person;

typedef struct _tagPerson2
{
char name[10];
char number[10];
}Person2;


//开启服务
void COppDlg::OnButton1()
{
if(m_sckServer.Create(9000))
{
m_sckServer.Listen();
}
else
{
MessageBox("服务器启动失败");
return;
}

SOCKET sck=m_sckServer.Detach();
AfxBeginThread(ThreadFun,(LPVOID)sck);
}

//发送数据
void COppDlg::OnButton2()
{
m_sckClient.Create();
int bRet=m_sckClient.Connect("127.0.0.1",9000);
if(bRet)
{
Person p;
memset(&p,0,sizeof(p));
memcpy(p.name,"1234567890abcdefgh",strlen("1234567890abcdefgh"));
memcpy(p.number,"abcdefgh1234567890",strlen("abcdefgh1234567890"));

m_sckClient.Send((char*)&p,sizeof(p),0);
}
}

UINT COppDlg::ThreadFun(LPVOID lpVoid)
{
AfxSocketInit();

SOCKET sck=(SOCKET)lpVoid;

CSocket m_sckServer,tmpSocket;
m_sckServer.Attach(sck);


Person2 p;

int b=sizeof(p);

CString strName,strNumber;
while(true)
{
memset(&p,0,sizeof(p));
m_sckServer.Accept(tmpSocket);
tmpSocket.Receive((char*)&p,sizeof(p),0);
b=sizeof(p);
strName.Format("%s",p.name);
strNumber.Format("%s",p.number);
}

return 0L;
}


接收的结构,跟发送的结构是不一样的。
发送的时候,每个参数都是18个字符。

接收的每个变量长度都是10个字节。

但是实际接收后,strName="1234567890abcdefgh";
strNumber="abcdefgh";

有没有什么办法,让Person2 都只接收 规定大小的字符数呢?
...全文
267 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
findcsdn 2010-04-14
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 cattycat 的回复:]

发送的结构会完整的发过来,你接收端的结构体的char数组被覆盖了。所以你读到的是你说的那个样子。
[/Quote]


如果程序是这样写

Receive((char*)&Person2,sizeof(Person2),0);

怎么可能把别人的数据全部接收到。


herman~~ 2010-04-14
  • 打赏
  • 举报
回复
既然是自己的通讯端,那就可以屏蔽掉恶意的消息长度不匹配的攻击
「已注销」 2010-04-14
  • 打赏
  • 举报
回复
唉,楼主还处于梦寐阶段,还是先不要讨论这些命题为好。
cqruan 2010-04-14
  • 打赏
  • 举报
回复

typedef struct _tagPerson3
{
char name[100];
char number[100];
}Person3;

typedef struct _tagPerson2
{
char name[10];
char number[10];
}Person2;



因为我的发送端和接收端源文件不小心泄露了。
不怀好意的人,可以构造这个shell攻击代码,向我的接收端发送数据。
而且我发现有很多垃圾数据发送到我的接收端上。


我的处理是这样的:
在执行完:Receive((char*)&Person2,sizeof(Person2),0);
后,就立即把里面的char数组,转化成CString(MFC数据字符串类型)
用的是CString的Foramt方法。

然后在用CString去继续下面的操作。

我现在担心的就是在接收的时候,会不会收到shell攻击,如果会,我的代码应该如何去防止?


cattycat 2010-04-13
  • 打赏
  • 举报
回复
发送的结构会完整的发过来,你接收端的结构体的char数组被覆盖了。所以你读到的是你说的那个样子。
findcsdn 2010-04-13
  • 打赏
  • 举报
回复
不管是用什么数据结构接收数据,都要规定数据长度呀。
别人用 _tagPerson3 发送200个字节数据,可是这边你用 _tagPerson2 接收只能接收20个字节,其他字节舍弃,还是不会溢出,这就是要规定缓冲区长度的重要意义。


栈的作用很特殊,存储了程序的运行流程,所以只要改变栈的数据就可以改变程序流程。
缓冲区溢出的攻击方法,要求缓冲区必须是栈里分配,另一个是要求客户端主动配合接收数据存储到缓冲区而且要超出缓冲区。


上面的例子中,本来程序只有20个字节,如果你非要接收200个字节,那我们也没办法啦。


yutaooo 2010-04-13
  • 打赏
  • 举报
回复

shellcode想要运行有两个条件。1. shellcode被传送到了你的机器上。2. 能够跳转到shellcode这段代码。

仅仅是将shellcode上传给你,只是八字有了一撇,还不能满足运行条件。

缓冲溢出的一个主要目的是为了能够跳转到sc。比如,早期,基于栈上缓冲区溢出,就有可能覆盖函数的返回地址。通过精心的计算,能够将覆盖的内够设定为shellcode的地址,如此在函数返回后可以掉转到sc。

现在基于堆的溢出也有,反正是方式多样。

对于第一点,也有技术处理。比如,对传送来的过滤检查等等。
cqruan 2010-04-13
  • 打赏
  • 举报
回复
我想请问的就是:

如果别人给我发送的是:
typedef struct _tagPerson3
{
char name[100];
char number[100];
}Person3;

而且name里面是保存的 shell攻击 代码;

而我用:
typedef struct _tagPerson2
{
char name[10];
char number[10];
}Person2;

这个结构接收,会不会出执行 他的 shell代码呢?
findcsdn 2010-04-13
  • 打赏
  • 举报
回复

以前的函数传参数都是只传缓冲区指针,不传长度,所以才能溢出,现在的函数基本上都规定了缓冲区指针和长度两个参数,所以一般不会再遭到这种攻击。

只要接收的数据量不大于缓冲区就行了,没什么困难吧。
cqruan 2010-04-13
  • 打赏
  • 举报
回复
怎么没人进来噢,自己再顶一下。
cqruan 2010-04-13
  • 打赏
  • 举报
回复
自己顶一下

64,636

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧