VC++ 从抓包到POST提交 实现自动投票
抓包工具我选的是:httpwatch7
浏览器:IE8 FireFox3(httpwatch7好像就支持FireFox的2~7版本)
开发工具:VS 2010
操作系统:WindowsXP SP3
一,下载并安装httpwatch
安装好后在IE(或FireFox)的工具栏下面就会有httpwatch的选项,选择就可以打开抓包的界面了
httpwatch的工作界面如下:
、
等待投票网页完全载入(排除无关数据减少我们的分析量)后,点击上图中的红色“Record”按钮,开始抓包。
点击网页中的投票按钮,等待网页响应载入完毕后点击"Stop"按钮,OK.这样就得到了我们想要的数据。当然一次成功的封包分析过程可能
需要我们多次抓包找出其中变化的数据(我们可以称之为“变量”或“参数”),这些参数就是我们要POST 的数据(当然我们前面几次抓包的过程中要有意识的改变提交的数据)。
有些比较复杂的站点的参数的变化可能看起来很没有规律,其实不然,大部分都在本地浏览器的脚本(如JavaScript)里生成的,所以对于这些变量我们可以找出
其生成的方法,我们自己模拟生成即可。如:有的站点在POST的时候有个不断在变化的SID,而这个SID和我们的输入没有任何关系,通过看看JS代码发现它(SID)是
GetDate()+“一个常量”,那么我们在填写POST数据时就可以这么写:GetDate()+“那个常量”。
可能有些提交表单的地方还有验证码,大部分情况下我们都可以通过右键验证码图片,查看其属性来获取到其生成验证码图片的路径,我们可以在界面程序上画一个图像控件
来显示它,一般图片都是一字节集的形式返回的,我们做好处理工作即可(喜欢用易语言的同学的注意了,PNG格式的图片用一般的图像控件可是无法显示的哦,得用透明图片控件)。
二,抓包,获取”参数“
好了,废话说了一大堆,下面是我抓包获取到的:
先来张图吧:
来到"POST"选项按钮:
看到这个其实,它已经帮我们找到了我们前面所说的“参数”,但是我们绝不能过度依赖工具的分析,很多情况都需要我们多次抓包手工分析才能得出结果的。
在看看“Stream“选项卡:
其中我标注为”发送数据区“的地方很重要,这里就是我们后面编程要POST(提交)的数据
在看下”Headers“选项卡:
其中我圈起来的地方也用的着,我们发送request请求是的头部数据和附加数据部分
三,OK,一切具备只缺代码实现了
我就这届上代码了,代码里有比较详细的注释的
/*===================================*/
/*日期:2013-1-8 */
/*作者:eldn */
/*功能:自动投票 */
/*===================================*/
#include <WinInet.h>
#pragma comment(lib,"Wininet.lib")//包含头文件及到入库
void PostAutoVoteDlg()
{
char szAccept[] = "Accept: */*"; //接受文件的类型
CString strHeaders = _T("Content-Type: application/x-www-form-urlencoded\r\n");
char szReferer[] = "Referer: http://henan.qq.com/zt/2012/jy/index.htm"; //这个最好写下,不然有的网站说盗链什么的检测不通过
CString szFormData = "PjtID=3445117&result=0&sbj_3513018%5B%5D=246293"; //我们上面分析出来的”参数“
HINTERNET hSession;
HINTERNET hConnect;
HINTERNET hRequest;
BOOL bReturn = FALSE;
// 之前使用Socket,现在使用Wininet相关API建立链接 ,初始化 WinInet.dll 并联接服务器,返回相应的句柄
hSession = InternetOpen("AutoVoteVisPostMethod",
INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0); //初始化 WinInet.dll,开始 HTTP会话,建立 HTTP 连接
hConnect = InternetConnect(hSession,"input.vote.qq.com",
INTERNET_DEFAULT_HTTP_PORT,NULL,NULL,INTERNET_SERVICE_HTTP,0,1); //建立 Internet 的连接,开始 HTTP会话,
hRequest = HttpOpenRequest(hConnect,"POST","survey.php",
"HTTP/1.1",szReferer,(LPCSTR *)&szAccept,INTERNET_FLAG_RELOAD,1); //打开一个 HTTP 请求的句柄
// 提交数据表单
LPVOID pBuf = (LPVOID)szFormData.GetBuffer(szFormData.GetLength());
bReturn = HttpSendRequest(hRequest,
strHeaders,-1L,pBuf,szFormData.GetLength()); //向 HTTP 服务器发送指定的请求
//HttpAddRequestHeaders 添加一个或多个 HTTP 请求报头到 HTTP请求句柄
if(!bReturn)
{
MessageBox("发送Http请求失败!","提示",MB_ICONERROR | MB_OK);
return;
}
char szRecvBuf[1024]; // 接受数据缓冲区
DWORD dwNumberOfBytesRead; // 服务器返回大小
DWORD dwRecvTotalSize=0; // 接受数据总大小
DWORD dwRecvBuffSize=0; // 接受数据buf的大小
CFile m_File; // 将返回数据写入文件
CString strTemp; // 临时消息框
m_File.Open("RecvData.tmp",CFile::modeWrite | CFile::modeCreate,NULL);
memset(szRecvBuf,0,1024);
do
{
// 开始读取数据
bReturn = InternetReadFile(hRequest,szRecvBuf,1024,&dwNumberOfBytesRead); //使用你提供的缓冲读指定的字节
if(!bReturn)
{
MessageBox("InternetReadFile Error !","提示",MB_ICONERROR | MB_OK);
break;
}
// 统计接受数据的大小
szRecvBuf[dwNumberOfBytesRead] = '\0';
dwRecvTotalSize += dwNumberOfBytesRead;
dwRecvBuffSize += strlen(szRecvBuf);
// 将缓冲区写入文件
m_File.Write(szRecvBuf,strlen(szRecvBuf));
m_File.Flush();
} while(dwNumberOfBytesRead !=0);
// 检查接受到的数据包是否完整
m_File.Close();
if(dwRecvTotalSize != dwRecvBuffSize)
{
MessageBox("接受数据时丢包,返回大小不一致!");
return ;
}
CString str=""; // 全部内容
CString strLine=""; // 单行内容
CStdioFile file; // 文件对象
if(!file.Open("RecvData.tmp",CFile::modeRead | CFile::typeText,NULL))
{
CString strTemp;
strTemp.Format("Open file error:%d",GetLastError());
MessageBox(strTemp);
return;
}
// 按行读取tmp全部内容
while(file.ReadString(strLine))
{
str = str + strLine;
}
file.Close();
if(str.Find("提交成功,谢谢参与!",0)>=1)
{
MessageBox("投票成功!","提示");
}
else
{
MessageBox("投票失败!","提示",MB_OK);
}
// 删除临时文件、释放内存
DeleteFile("RecvData.tmp");
}