分享
 
 
 

网上投票作弊的技术实现(纯技术交流,勿用作他途!!)

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

申明:纯技术交流,勿用作他途!!

文章中所讨论的技术应用范围其实还是比较广的,除了投票这种比较阴的应用,还可以完成比如自动填写表单、邮箱自动申请、网站注册等功能。

这里提供的方法有两种:

方法1: 通过IE控件提供的COM接口实现。这种方法是通过IHTMLDocument2接口编辑网页表单(有时得修改网页代码),然后触发一个事件提交网页。 这种方法由于使用了IE控件,打开网页时会下载很多与应用无关的数据,如图片等(当然你可以在IE中把图片之类的选项关掉),效率很低,而且每投一票就得开一个IE控件,如果你的机子差些,等着按Reset吧~~。另外,这种方法编码比较多,挺烦。

方法2: 通过WinInet API来实现表单提交的工作。这种方法要比前面那种方法高明多了,不但执行效率高,耗资源少,而且具体实现起来也比上一种简单。

下面分别把两种方法介绍一下:

方法1:通过IE控件提供的COM接口实现

1、我的程序是基于对话框的,不是用的HtmlView,所以要先在对话框上放一个IE控件(Insert ActiveX Control,里面有一个Microsoft Web浏览器),给这个IE控件起个名字,比如m_ctrlWeb。另外要记着加上<mshtml.h>头文件,IE COM接口的东西都在里面放着。<comdef.h>和<atlbase.h>如果没有的话也要加上。

2、用ClassWizard加入DownloadComplete事件的响应,这样网页下载完了你就可以做填表单之类的工作了。当然你也可以在ProgressChange之类的事件中作这些操作了,不过这样你就得判断网页是不是差不多下载到合适的位置了,要图省事,直接用DownloadComplete算了。

3、下一步就是用这个控件打开目标网页了,什么时候打开你自己看着办,我是在InitDialog里面打开的,代码如下:

COleVariant vaUrl="http://www.onlytest.net";

m_ctrlWeb.Navigate2(&vaUrl, &vtMissing, &vtMissing, &vtMissing, &vtMissing);

其中那个vtMissing是用作缺省参数的。

4、然后就是主要的操作了。这些操作都放在OnDownloadCompleteExplorer里。为了方便,我写了几个函数用来完成特定的功能,在具体说明OnDownloadCompleteExplorer中进行的操作之前,先把这几个函数解释一下。

//功能:判断网页里是不是有strName指定的元素

//参数: pobjAllElement:网页中所有元素的集合

// strName:网页中元素的id或name

bool HasItem(IHTMLElementCollection *pobjAllElement,CString strName)

{

CComPtr<IDispatch>pDisp;

pobjAllElement->item(COleVariant(strName),COleVariant((long)0),&pDisp);

if(pDisp==NULL)

return false;

else

return true;

}

//功能:在网页的文本框中输入字符串

//参数: pobjAllElement:网页中所有元素的集合

// strName:要编辑的文本框的id或name

// strText:要在文本框中写入的内容

void PutIEText(IHTMLElementCollection *pobjAllElement,CString strName,CString strText)

{

CComPtr pDisp;

pobjAllElement->item(COleVariant(strName),COleVariant((long)0),&pDisp);

CComQIPtr pElement;

if(pDisp==NULL)

{

AfxMessageBox(strName + "没有找到!");

}

else

{

pElement=pDisp;

pElement->put_value(strText.AllocSysString());

}

}

//功能:提交一个网页的Form

//参数: pobjAllElement:网页中所有元素的集合

// strName:可以提交Form的按钮的id或name(也可以直接Form的submit提交)

void SubmitPage(IHTMLElementCollection *pobjAllElement,CString strName)

{

CComPtrpDisp;

pobjAllElement->item(COleVariant(strName),COleVariant((long)0),&pDisp);

CComQIPtrpElement;

if(pDisp==NULL)

{

AfxMessageBox(strName + "没有找到!");

}

else

{

pElement=pDisp;

pElement->click();

}

}

//功能:选中网页中的一个CheckBox (其实就是点击)

//参数: pobjAllElement:网页中所有元素的集合

// strName:要选中的CheckBox的id或name

void CheckItem(IHTMLElementCollection *pobjAllElement,CString strName)

{

CComPtr pDisp;

pobjAllElement->item(COleVariant(strName),COleVariant((long)0),&pDisp);

CComQIPtr<IHTMLElement, &IID_IHTMLElement>pElement;

if(pDisp==NULL)

{

AfxMessageBox(strName + "没有找到!");

}

else

{

pElement=pDisp;

pElement->click();

}

}

使用这几个函数可以很轻松地完成投票操作。下面列出OnDownloadCompleteExplorer中的代码。

另假设投票页面为http://www.onlytest.com/vote.htm,数据提交到http://www.onlytest.com /vote2.asp

void CVoteDlg::OnDownloadCompleteExplorer()

{

// TODO: Add your control notification handler code here

IHTMLElementCollection *objAllElement=NULL;

IHTMLDocument2 *objDocument=NULL;

CString strUrl,strTemp;

strUrl=m_ctrlWeb.GetLocationURL();//得到当前网页的URL

if(strUrl.IsEmpty())

return;

objDocument=(IHTMLDocument2 *)m_ctrlWeb.GetDocument(); //由控件得到IHTMLDocument2接口指针

objDocument->get_all(&objAllElement); //得到网页所有元素的集合

//由于所有页面下载完后都会执行这个函数,所以必须根据URL判断消息来源网页

if(strUrl=="http://www.onlytest.com/vote.htm")

{

CComPtr<IDispatch>pDisp;

if(HasItem(objAllElement,"voteform")==true) //voteform为投票选项所在的Form

{

objAllElement->item(COleVariant("voteform"),COleVariant((long)0),&pDisp);

CComQIPtr<IHTMLFormElement , &IID_IHTMLFormElement >pElement;

if(pDisp==NULL)

{

//接口指针获取失败,结束程序,不另外作处理,原因见后

EndDialog(IDOK);

return;

}

else

{

//如果投票结果在新窗口打开,则应该修改网页代码,让结果在本控件中显示

pElement=pDisp;

pElement->put_target(CComBSTR("_self")); //等效于target="_self"

pElement->put_action(CComBSTR("vote2.asp"));//等效于action="vote2.asp"

}

CheckItem(objAllElement,"chk2"); //将form中id为chk2的CheckBox选中

SubmitPage(objAllElement,"vote"); //提交网页,vote为submit按钮的id或name

}

}

else if(strUrl=="http://www.onlytest.com/vote2.asp")

{

EndDialog(IDOK); //如果投票处理页面已经下载完毕,则结束程序,原因见后。

}

}

现在票已经投出去了,但看过程序你可能会奇怪,为什么投完票或中间出了错要用EndDialog结束程序,而不是继续投票呢?事情是这样的,有些网站一个session只能投一票,而一个IE控件创建好,与服务器连接后(有了Session),那个Session Key就定好了(一家之言),所以如果继续用这个IE控件投票,服务器会告诉你你已经投过票了(当然如果投票程序写的笨,没管这个,那就简单多了)。这个问题本来我想通过分析WinInet API的运行过程对付的,可是好像很麻烦,所以用了一个很笨的但简单的方法:投票程序作为一个程序,然后另一个程序调用这个投票程序,投完票后投票程序结束,主程序再次运行投票程序,如此反复。至于投票程序数量的限制之类的东西,用共享内存段是最简单的(一家之言),具体就不在这里讨论了。

方法2:通过WinInet API来实现表单提交的工作

这种方法实现代码量很少,而且由于不需要下载太多的无用数据(如图片等),form所在的页面也不需要下载,所以效率要高得多,另外实现代码是一个函数,很适合用在线程中。

用这种方法关键是要知道应该给服务器提交些什么数据如果自己去看网页文件,然后分析应该向服务器提交什么数据,网页很简单时还差不多,如果网页很复杂,那就属于费力不讨好的事。现在不是考试,那种事情我们就不做了,现在有一个更简单的办法,就是用Win2000下的网络监视器,手工投一票看看向服务器提交了些什么数据。这样我们就可以把那数据中属于HTTP协议的部分Copy下来。直接从监视器里拷出来的数据是没法用的,因为监视器显示文本的部分把回车换行之类的字符都用小数点代替了,这些部分要先改回原来的回车、换行(HTTP头部分的就可以不用管了,只要你能分清边界就可以了)。另外注意,提交信息中可能会有Content-Length这个信息,如果你修改了提交数据的内容,而且数据长度发生了变化,Content-Length项的值一定要跟着改。比如Content-Length原来的值是100,数据中有一条数据“1”,你现在改成了“12”,则Content-Length一定要改成101,否则服务器会返回错误。

下面列出的就是投票函数:

UINT Vote(LPVOID)

{

CInternetSession session;

theApp.m_nThreads++; //用来记录投票线程数的

try

{

CHttpConnection* pConnection =session.GetHttpConnection("www.onlytest.net"); //网站服务器

CHttpFile* pFile = pConnection->OpenRequest(CHttpConnection::HTTP_VERB_POST,"vote2.asp"); //直接向投票处理页面提交数据

//下面向提交数据中添加HTTP头,这些可以由网络监视器得到

pFile->AddRequestHeaders("Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*");

pFile->AddRequestHeaders("Referer: http://www.onlytest.net/vote.htm");

pFile->AddRequestHeaders("Accept-Language: zh-cn");

pFile->AddRequestHeaders("Content-Type: multipart/form-data; boundary=---------------------------7d11dc24268052c");

pFile->AddRequestHeaders("Accept-Encoding: gzip, deflate");

pFile->AddRequestHeaders("User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");

pFile->AddRequestHeaders("Content-Length: 1351");

pFile->AddRequestHeaders("Connection: Keep-Alive");

pFile->AddRequestHeaders("Cache-Control: no-cache");

//HTTP头后面就应该是真正的数据了,下面theApp.m_strFormData中就是要提交的数据,服务器处理返回的信息在pFile中

pFile->SendRequest(NULL,0,theApp.m_strFormData.GetBuffer(0),theApp.m_strFormData.GetLength()); //提交所有数据

//其实到这里投票已经可以结束了,不过你如果想看看成果,完全可以把返回的页面分析分析,得到些数据

char szBuffer[11001]; //用来存放返回的处理页面,要多大看实际情况。当然也可以动态分配,不嫌累的话

int nLen=pFile->Read(szBuffer,11000);//读取返回的内容,其实是投票结果页面的HTML代码

szBuffer[nLen]=0;

CString strTemp=szBuffer; //CString虽然滥了些,但用着就是方便,嘿嘿~

pFile->Close(); //数据读出来后把该关闭的东西都关掉

pConnection->Close();

delete pFile;

delete pConnection;

session.Close();

//下面的代码就是用来分析HTML代码来得到你感兴趣的数据了,和投票没什么关系,就不详细解释了

int nPos=strTemp.Find("选项A");

int nTempPos=nPos;

if(nPos==-1)

{

theApp.m_nThreads--;

return 0;

}

nPos=strTemp.Find("table width=100><tr><td align=right>",nPos)+36;

int nEndPos=strTemp.Find("票",nPos);

m_nOurNum=atoi(strTemp.Mid(nPos,nEndPos-nPos));

nPos=strTemp.Find("<tr bgcolor=#DEE6EB><td align=center width=50>1</td>");

nPos=strTemp.Find("table width=100><tr><td align=right>",nPos)+36;

nEndPos=strTemp.Find("票",nPos);

m_nDiff=atoi(strTemp.Mid(nPos,nEndPos-nPos))-m_nOurNum;

m_nVote++;

}

catch(...)

{

}

theApp.m_nThreads--;

return 0;

}

可以看到,关键代码就那么几行,如果不分析投票结果,比方法1少多了,而且看着也没方法1那么乱。不过这种方法同样存在方法1说的那个Session重复问题。而且据我尝试,新开启线程Session也是重复。所以我估计那个Session Key是根据Process ID决定的(一家之言,欢迎大家讨论)。不过如果你同时启动N个线程,着N个线程都可以成功的把票投进去,而不会说“您已经投过票了”。估计是因为这些信息是同时提交上去的,服务器在处理一条信息时还不知道这个Session其实已经投过票了。是不是这个原因我也不清楚,大家可以讨论一下。

两种程序投票的方法就写到这里了。本人的水平实在一般,所以文章中有错误的话大家千万不要不屑一说啊,把错误指出来大家一起讨论一下。另外文中说到的那个Session的问题也希望大家讨论一下。

另外打个小广告:http://www.baizhuang.net,嘿嘿~~

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有