Java Interposer 中的堆栈粉碎
Posted
技术标签:
【中文标题】Java Interposer 中的堆栈粉碎【英文标题】:Stack Smashing in Java Interposer 【发布时间】:2012-06-27 12:18:49 【问题描述】:我正在编写一个 Java 插入器来修改与网络通信相关的系统调用。基本上,我想修改预期收件人的IP和端口。
代码在我的笔记本电脑上正常工作,但在大学电脑上,它给出了一个堆栈粉碎错误:
*** stack smashing detected ***: java terminated
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0xb7702dd5]
/lib/i386-linux-gnu/libc.so.6(+0xffd8a)[0xb7702d8a]
/home/mwaqar/vibe/ldinterposer_2.so(+0x28e4)[0xb77c98e4]
/home/mwaqar/vibe/ldinterposer_2.so(connect+0x9c5)[0xb77c9093]
/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/libnet.so(+0xceff)[0x8b226eff]
/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/libnet.so(Java_java_net_PlainSocketImpl_socketConnect+0x4c1)[0x8b227c51]
相关代码(connect系统调用的插入)如下:
int connect(int fd, const struct sockaddr *sk, socklen_t sl)
struct sockaddr_in *lsk_in = (struct sockaddr_in *) sk;
struct sockaddr_in6 *lsk_in6 = (struct sockaddr_in6 *) sk;
struct sockaddr_in addr4;
unsigned int len;
int nbytes, oport, tport, ret, i;
char ip_address[30];
char buffer[1024];
char tempBuffer[1024];
if((lsk_in->sin_family == AF_INET) || (lsk_in->sin_family == AF_INET6))
if(lsk_in->sin_family == AF_INET)
oport = ntohs(lsk_in->sin_port);
memcpy(&addr4.sin_addr.s_addr, &lsk_in->sin_addr.s_addr, sizeof(addr4.sin_addr.s_addr));
else if(lsk_in->sin_family == AF_INET6)
oport = ntohs(lsk_in6->sin6_port);
memcpy(&addr4.sin_addr.s_addr, lsk_in6->sin6_addr.s6_addr+12, sizeof(addr4.sin_addr.s_addr));
memset(buffer, '\0', sizeof(buffer));
sprintf(buffer, "%s%c%s%c%i", NAT_VM_CONNECT_RULE, NAT_VM_DELIMITER, (char *)inet_ntoa(addr4.sin_addr), NAT_VM_DELIMITER, oport);
nbytes = send(sock, buffer, strlen(buffer), 0);
if(DEBUG_MODE)
fprintf(stdout, "[LD_INTERPOSER] Sent[%s]\n", buffer);
memset(buffer, '\0', sizeof(buffer));
nbytes = recv(sock, buffer, sizeof(buffer), 0);
fprintf(stderr, "[LD_INTERPOSER] Received CONNECT [%s]\n", buffer);
memset(ip_address, '\0', sizeof(ip_address));
int pos = strrchr(buffer, NAT_VM_DELIMITER) - buffer;
strncpy(ip_address, buffer, pos);
ip_address[pos] = '\0';
tport = atoi(buffer + pos + 1);
if(lsk_in->sin_family == AF_INET)
lsk_in->sin_addr.s_addr = inet_addr(ip_address + 7);
lsk_in->sin_port = htons(tport);
else if(lsk_in->sin_family == AF_INET6)
inet_pton(AF_INET6, ip_address, &(lsk_in6->sin6_addr));
lsk_in6->sin6_port = htons(tport);
fprintf(stderr, "[LD_INTERPOSER] IP[%s], Port[%d] for VM[%s]\n", ip_address, tport, vm_ip);
int my_ret = real_connect(fd, sk, sl);
fprintf(stderr, "Done\n");
return my_ret;
这里,sock 是我在共享库的“构造函数”中初始化的套接字。
程序正常运行并打印完成。在最后(返回)行,它给出了堆栈粉碎错误。我不知道是什么原因造成的。
【问题讨论】:
抱歉,更新了代码。 堆栈粉碎错误是由检查可能的缓冲区溢出错误的内置机制引起的。检查您永远不会向buffer
或tempBuffer
写入超过它们各自大小的字节。
永远不要使用sprintf
,尤其是在您怀疑超限时。我不知道这是否是这里出错的原因,但这是首先要解决的问题。
你确定strrchr()
没有返回NULL
?
@buc:我确信buffer
和tempBuffer
没有溢出。它们的容量为 1024 字节,最多可容纳 100 个字符。
【参考方案1】:
我怀疑strrcr
在该行中返回NULL
int pos = strrchr(buffer, NAT_VM_DELIMITER) - buffer;
那么pos
会很大,下面几行会读写无效地址。
始终检查函数的返回值(尤其是当它们根据从程序外部接收的数据运行时)。
另外,正如我在评论中所写,永远不要使用sprintf
。我不知道它是否失败,因为我不知道NAT_VM_CONNECT_RULE
是什么。即使您计算了字节数并知道自己没问题,您仍然应该小心并改用snprintf
。
【讨论】:
我不认为你提到的那一行是问题所在。收到的回复格式为IP|port
(NAT_VM_DELIMITER
是字符“|”)。我必须把这些分开。如果该语句是问题所在,那么fprintf(stderr, "[LD_INTERPOSER] IP[%s], Port[%d] for VM[%s]\n", ip_address, tport, vm_ip);
行将不会打印正确的(单独的)IP 和端口。另外,我认为如果该语句是问题,程序将在那里终止,而不是工作到函数的倒数第二个语句fprintf(stderr, "Done\n");
。
也许这不是导致问题的原因,但它是一个错误。您应该先修复我向您展示的两个错误,然后尝试调试它。
我已经纠正了你提到的所有错误。还是一样的*** stack smashing detected ***
输出。以上是关于Java Interposer 中的堆栈粉碎的主要内容,如果未能解决你的问题,请参考以下文章