//登陆的参数 List< 2010-07-03 11:38 [收藏] 标签:龙之谷外挂,开心网里面有个争车位还蛮有意思的
车子少还好,车子多了就得一辆一辆的停,太麻烦了
于是就想弄个外挂看看,一搜索,一大堆外挂,用了一下还不错,
后来想了想,自己也写个几个小程序,也弄个山寨外挂看看,
于是GOOGLE,BAIDU,GO...
做一个Web游戏外挂需要的准备知识:
1) 需要有耐心
2) 熟悉HTML, JavaScript
3) 熟悉HTTP协议,特别是Cookie, URL的编码方式和POST, GET内容格式
4) 熟悉游戏本身,能抽象出最优的赚钱/升级的数学模型
5) 掌握一门语言,白菜萝卜都可以,我比较喜欢用Java和C#
6) 需要一些抓包的工具,比如HttpWatch
好了,来个例子,开心网争车位.语言:java,IDE:netbeans6.1
首先,我们看看一个正常用户玩的时候是怎么玩的。
1) 浏览器输入 www.kaixin001.com ,输入用户名,密码,点登陆
2) 登陆后选择左侧的“争车位”,进入到争车位
3) 看看自己的车哪些停车时间操作15分钟了,一一找个空的不免费的车位挪过去
4) 登出开心网,关闭浏览器
看看让程序怎么来实现1-4,龙之谷外挂。
1) 登陆开心网
在HttpWatch的帮助下,我们知道登陆是把FORM提交到/login/login.php,POST内容是:
email [ft=#006699,,
password 太复杂
url /
用apache的HttpClient可以方便的完成这个POST操作,然后得到服务器的返回,然后根据返回的内容里找一个关键字就可以判断这次登陆操作是否成功了。
以下是登陆代码片段
Java代码
CookieStore cookieStore = null; try { DefaultHttpClient httpclient = new DefaultHttpClient(); //登陆 //这里Constants是我自定义的一个常量类 HttpPost httpost = new HttpPost(Constants.LOGINURL); //登陆的参数 List<NameValuePair> nvps = new ArrayList<NameValuePair>(); //EMAIL nvps.add(new BasicNameValuePair(Constants.EMAIL, email)); //密码 nvps.add(new BasicNameValuePair(Constants.PASSWORD, password)); //URL nvps.add(new BasicNameValuePair(Constants.URL, "/")); httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); //执行登陆 HttpResponse response = httpclient.execute(httpost); //获取HTTP响应头中的Set-Cookie Header header = response.getFirstHeader("Set-Cookie"); HeaderElement[] elements = header.getElements(); if (elements != null) { for (HeaderElement element : elements) { if ("_user".equals(element.getName())) { // System.out.println(element.getValue()); if ("deleted".equals(element.getValue())) { System.out.println("登陆失败"); } else { System.out.println("登陆成功"); //获取cookies cookieStore = httpclient.getCookieStore(); } break; } } } return cookieStore; CookieStore cookieStore = null; try { DefaultHttpClient httpclient = new DefaultHttpClient(); //登陆 //这里Constants是我自定义的一个常量类 HttpPost httpost = new HttpPost(Constants.LOGINURL); //登陆的参数 List<NameValuePair> nvps = new ArrayList<NameValuePair>(); //EMAIL nvps.add(new BasicNameValuePair(Constants.EMAIL, email)); //密码 nvps.add(new BasicNameValuePair(Constants.PASSWORD, password)); //URL nvps.add(new BasicNameValuePair(Constants.URL, "/")); httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); //执行登陆 HttpResponse response = httpclient.execute(httpost); //获取HTTP响应头中的Set-Cookie Header header = response.getFirstHeader("Set-Cookie"); HeaderElement[] elements = header.getElements(); if (elements != null) { for (HeaderElement element : elements) { if ("_user".equals(element.getName())) { // System.out.println(element.getValue()); if ("deleted".equals(element.getValue())) { System.out.println("登陆失败"); } else { System.out.println("登陆成功"); //获取cookies cookieStore = httpclient.getCookieStore(); } break; } } } return cookieStore;
2) 登陆争车位
这次是一个GET操作,URL是/app/app.php?aid=1040。
需要说明一下的是,这里没有提供用户名密码,服务器怎么能知道是哪个用户呢?Cookie在这里就发挥了它的作用。
刚才在登陆的时候返回的CookieStore里存放的就是Cookies
然后所有的Http请求的Cookies都用它。
好了,取得这个页面以后,我们能得到很多信息:(这些信息是JSON格式)
a) 好友列表,每个好友的状态(在线/车位满)
b) 自己的车库信息,停了那些好友的哪些车,分别赚了多少钱
c) 自己的汽车信息,多少辆车,分别停在哪里,赚了多少钱
根据这些信息,我们可以得到一个停放的列表(车位不满的好友列表)
3) 挪车位
这个操作稍微复杂了一点点,具体的HTTP请求大家可以去分析一下
a)获取好友车位信息,
将有免费的车位的好友车位记录下来
部分代码如下
Java代码
DefaultHttpClient httpclient = new DefaultHttpClient(); //登陆 HttpPost httpost = new HttpPost(FRIENDPARK); //登陆的参数 List<NameValuePair> nvps = new ArrayList<NameValuePair>(); //EMAIL nvps.add(new BasicNameValuePair("_", null)); //好友ID nvps.add(new BasicNameValuePair("puid", puid)); //验证字符串 nvps.add(new BasicNameValuePair("verify", verify)); httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); //设置COOKIES HttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); //进入好友车位 ResponseHandler<String> responseHandler = new BasicResponseHandler(); //获取好友数据 String responseBody = httpclient.execute(httpost, responseHandler, localContext); JSONObject friendJson = new JSONObject(responseBody); // JSONArray parks = friendJson.getJSONArray("parking"); //这里CommonFunction是我自定义的一个解析json数组的一个工具类 List list = CommonFunction.parseJsonArray(friendJson.getString("parking"), Parking.class); DefaultHttpClient httpclient = new DefaultHttpClient(); //登陆 HttpPost httpost = new HttpPost(FRIENDPARK); //登陆的参数 List<NameValuePair> nvps = new ArrayList<NameValuePair>(); //EMAIL nvps.add(new BasicNameValuePair("_", null)); //好友ID nvps.add(new BasicNameValuePair("puid", puid)); //验证字符串 nvps.add(new BasicNameValuePair("verify", verify)); httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); //设置COOKIES HttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); //进入好友车位 ResponseHandler<String> responseHandler = new BasicResponseHandler(); //获取好友数据 String responseBody = httpclient.execute(httpost, responseHandler, localContext); JSONObject friendJson = new JSONObject(responseBody); // JSONArray parks = friendJson.getJSONArray("parking"); //这里CommonFunction是我自定义的一个解析json数组的一个工具类 List list = CommonFunction.parseJsonArray(friendJson.getString("parking"), Parking.class);
注:解析服务器返回的HTML我使用的是htmlparse
b) 如果是免费车位,说有3个活动不过还没具体说是什么,停车,当然还要判断该车位上是否有汽车
在JavaScript里有代码:
v_park_free = (v_parkid >> 16) & 0xff;
if (v_park_free)
{
v_mycar += '免费车位';
}
else
{
v_mycar += '私家车位';
}
用JAVA代码模拟一下
Java代码
Integer parkid = Integer.parseInt(parking.getParkid()); //flag=1是免费车位,flag=0不是免费车位 int flag = (parkid >> 16) & 0xff; 停车: DefaultHttpClient httpclient = new DefaultHttpClient(); //停车 HttpPost httpost = new HttpPost(PARKINGURL); //停车的参数 List<NameValuePair> nvps = new ArrayList<NameValuePair>(); nvps.add(new BasicNameValuePair("_", null)); nvps.add(new BasicNameValuePair("acc", parkEntity.getAcc())); nvps.add(new BasicNameValuePair("carid", carid)); nvps.add(new BasicNameValuePair("first_fee_parking", "0")); nvps.add(new BasicNameValuePair("neighbor", neighbor)); nvps.add(new BasicNameValuePair("park_uid", parkuid)); nvps.add(new BasicNameValuePair("parkid", parking.getParkid())); nvps.add(new BasicNameValuePair("verify", parkEntity.getVerify())); httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); //设置COOKIES HttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.COOKIE_STORE, parkEntity.getCookieStore()); ResponseHandler<String> responseHandler = new BasicResponseHandler(); //获取停车信息 String responseBody = httpclient.execute(httpost, responseHandler, localContext); System.out.println(responseBody); Map map = CommonFunction.parseJSON(responseBody); //获取停车结果 res = Integer.parseInt((String) map.get("errno")); Integer parkid = Integer.parseInt(parking.getParkid()); //flag=1是免费车位,flag=0不是免费车位 int flag = (parkid >> 16) & 0xff; 停车: DefaultHttpClient httpclient = new DefaultHttpClient(); //停车 HttpPost httpost = new HttpPost(PARKINGURL); //停车的参数 List<NameValuePair> nvps = new ArrayList<NameValuePair>(); nvps.add(new BasicNameValuePair("_", null)); nvps.add(new BasicNameValuePair("acc", parkEntity.getAcc())); nvps.add(new BasicNameValuePair("carid", carid)); nvps.add(new BasicNameValuePair("first_fee_parking", "0")); nvps.add(new BasicNameValuePair("neighbor", neighbor)); nvps.add(new BasicNameValuePair("park_uid", parkuid)); nvps.add(new BasicNameValuePair("parkid", parking.getParkid())); nvps.add(new BasicNameValuePair("verify", parkEntity.getVerify())); httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); //设置COOKIES HttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.COOKIE_STORE, parkEntity.getCookieStore()); ResponseHandler<String> responseHandler = new BasicResponseHandler(); //获取停车信息 String responseBody = httpclient.execute(httpost, responseHandler, localContext); System.out.println(responseBody); Map map = CommonFunction.parseJSON(responseBody); //获取停车结果 res = Integer.parseInt((String) map.get("errno"));
verify这个参数也需要从首页上提取
上面的acc要注意,这个acc是网页的一个动态js方法返回的数据
所以要获取这个动态的acc方法,然后执行该js获取结果
这是我的代码
Java代码
/** * 调用自动生成的ACC方法 * @param script * @return */ public static String invokeAccScript(String script) { String acc = null; try { StringBuilder builder = new StringBuilder(); BufferedReader reader1 = new BufferedReader(new StringReader(script)); reader1.readLine(); while ((acc = reader1.readLine()) != null) { if (acc.startsWith("function notice()")) { break; } else { builder.append(acc); } } reader1.close(); ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine engine = m.getEngineByName("javascript"); if (engine != null) { engine.eval(builder.toString()); Invocable invocableEngine = (Invocable) engine; //调用acc方法获取验证码 acc = invocableEngine.invokeFunction("acc").toString(); } } catch (Exception e) { e.printStackTrace(); } return acc; } /** * 调用自动生成的ACC方法 * @param script * @return */ public static String invokeAccScript(String script) { String acc = null; try { StringBuilder builder = new StringBuilder(); BufferedReader reader1 = new BufferedReader(new StringReader(script)); reader1.readLine(); while ((acc = reader1.readLine()) != null) { if (acc.startsWith("function notice()")) { break; } else { builder.append(acc); } } reader1.close(); ScriptEngineManager m = new ScriptEngineManager(); ScriptEngine engine = m.getEngineByName("javascript"); if (engine != null) { engine.eval(builder.toString()); Invocable invocableEngine = (Invocable) engine; //调用acc方法获取验证码 acc = invocableEngine.invokeFunction("acc").toString(); } } catch (Exception e) { e.printStackTrace(); } return acc; }
4) 登出睡觉
GET URL: /login/logout.php
操作差不多就这些。
注:解析HTML使用的是Htmlparse
模拟HTTP请求使用的是HttpClient
解析json使用的是json.jar
当然界面使用的是swing,SUN说jdk1.6的swing效率有了很大提升噢!
今天把源代码加上。。。
写得不好的地方请拍砖