最近很流行的一款微信小游戏《海盗来了》,用来打发时间还不错,就是建岛和转盘太慢了,于是用Fiddler抓了下包,分析了下请求报文,发现所有的请求都需要sign签名,尝试了几次都得不到签名值,于是搞了个安卓模拟器,把小游戏的源码拷出来分析了下。
以下是我解包出来并且解码后的海盗来了game.js 源码:gamezip
发现请求的签名算法就是普通的字典排序,拼成URL后把&符号去掉,再进行MD5签名!
例如:sign=md5(uid=666t=666secret=666)
试了下,还是可以用的,但请求的频率不宜过高,我的一个号就是这样被封了,所以。。。
Talk is cheap, show you the code :
解释一下,这里用到了一个RelynSpider类,是我自己的爬虫框架,就不贴出来了,其实就是简单的POST请求即可(POST的时候,User-Agent记得跟微信一样)~~
public class RelynPirate { private static RelynSpider relynSpider = new RelynSpider(); public static void start(String encryptedCode, String uid, String userId, String island) { String url = "https://pirate-api.hortor002.com/game/entry/wxgame"; Map<String, Object> map = new HashMap<String, Object>(); Map<String, String> dataMap = new HashMap<String, String>(); String t = String.valueOf(System.currentTimeMillis()).substring(0, 10); String resp = ""; String sign = ""; String param = ""; map.put("encryptedCode", encryptedCode); resp = relynSpider.postWechat(url, map); System.out.println("HTML >> " + resp); resp = resp.substring(resp.indexOf("secret/":/"") + 9); String secret = resp.substring(0, resp.indexOf("/"")); System.out.println("secret >> " + secret); // 基础登录 url = "https://pirate-api.hortor002.com/game/basic/login"; dataMap = new HashMap<String, String>(); dataMap.put("userId", userId); dataMap.put("isWxGame", "true"); dataMap.put("t", t); dataMap.put("secret", secret); param = RelynSpider.formatUrlMap(dataMap, false, false); System.out.println("param >> " + param); param = param.replaceAll("&", ""); // 把&去掉 sign = RelynSpider.md5(param); System.out.println("sign >> " + sign); map = new HashMap<String, Object>(); map.put("userId", userId); map.put("isWxGame", "true"); map.put("t", t); map.put("secret", secret); map.put("sign", sign); resp = relynSpider.postWechat(url, map); System.out.println("HTML >> " + resp); // 领取并赠送能量 url = "https://pirate-api.hortor002.com/game/friend/donate"; dataMap = new HashMap<String, String>(); dataMap.put("uid", uid); dataMap.put("fid", "0"); dataMap.put("isWxGame", "true"); dataMap.put("t", t); dataMap.put("secret", secret); param = RelynSpider.formatUrlMap(dataMap, false, false); System.out.println("param >> " + param); param = param.replaceAll("&", ""); // 把&去掉 sign = RelynSpider.md5(param); System.out.println("sign >> " + sign); map = new HashMap<String, Object>(); map.put("uid", uid); map.put("fid", "0"); map.put("isWxGame", "true"); map.put("t", t); map.put("secret", secret); map.put("sign", sign); resp = relynSpider.postWechat(url, map); System.out.println("HTML >> " + resp); // 金矿 url = "https://pirate-api.hortor002.com/game/island/collect"; dataMap = new HashMap<String, String>(); dataMap.put("uid", uid); dataMap.put("isWxGame", "true"); dataMap.put("t", t); dataMap.put("secret", secret); param = RelynSpider.formatUrlMap(dataMap, false, false); System.out.println("param >> " + param); param = param.replaceAll("&", ""); // 把&去掉 sign = RelynSpider.md5(param); System.out.println("sign >> " + sign); map = new HashMap<String, Object>(); map.put("uid", uid); map.put("isWxGame", "true"); map.put("t", t); map.put("secret", secret); map.put("sign", sign); resp = relynSpider.postWechat(url, map); System.out.println("HTML >> " + resp); // 转盘 int length = 100; while (length > 34) { // 这里的等待5秒是我被封号后加上去的,可根据实际情况适当调整 try { Thread.sleep(5000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } url = "https://pirate-api.hortor002.com/game/roller/roll"; dataMap = new HashMap<String, String>(); dataMap.put("uid", uid); dataMap.put("bet", "1"); dataMap.put("isWxGame", "true"); dataMap.put("t", t); dataMap.put("secret", secret); param = RelynSpider.formatUrlMap(dataMap, false, false); System.out.println("param >> " + param); param = param.replaceAll("&", ""); // 把&去掉 sign = RelynSpider.md5(param); System.out.println("sign >> " + sign); map = new HashMap<String, Object>(); map.put("uid", uid); map.put("bet", "1"); map.put("isWxGame", "true"); map.put("t", t); map.put("secret", secret); map.put("sign", sign); resp = relynSpider.postWechat(url, map); System.out.println("HTML >> " + resp); length = resp.length(); System.out.println("length >> " + length); if (length > 600) { if (resp.indexOf("stealIslands/":null") != -1) { resp = resp.substring(resp.indexOf("uid/":") + 5); String puid = resp.substring(0, resp.indexOf(",")); // 攻击 System.out.println("[*] 攻击"); url = "https://pirate-api.hortor002.com/game/pvp/attack"; dataMap = new HashMap<String, String>(); dataMap.put("uid", uid); dataMap.put("puid", puid); dataMap.put("building", "3"); dataMap.put("isWxGame", "true"); dataMap.put("t", t); dataMap.put("secret", secret); param = RelynSpider.formatUrlMap(dataMap, false, false); System.out.println("param >> " + param); param = param.replaceAll("&", ""); // 把&去掉 sign = RelynSpider.md5(param); System.out.println("sign >> " + sign); map = new HashMap<String, Object>(); map.put("uid", uid); map.put("puid", puid); map.put("building", "3"); map.put("isWxGame", "true"); map.put("t", t); map.put("secret", secret); map.put("sign", sign); resp = relynSpider.postWechat(url, map); System.out.println("HTML >> " + resp); } else { // 盗窃 System.out.println("[*] 盗窃"); url = "https://pirate-api.hortor002.com/game/pvp/steal"; dataMap = new HashMap<String, String>(); dataMap.put("uid", uid); dataMap.put("idx", "1"); dataMap.put("isWxGame", "true"); dataMap.put("t", t); dataMap.put("secret", secret); param = RelynSpider.formatUrlMap(dataMap, false, false); System.out.println("param >> " + param); param = param.replaceAll("&", ""); // 把&去掉 sign = RelynSpider.md5(param); System.out.println("sign >> " + sign); map = new HashMap<String, Object>(); map.put("uid", uid); map.put("idx", "1"); map.put("isWxGame", "true"); map.put("t", t); map.put("secret", secret); map.put("sign", sign); resp = relynSpider.postWechat(url, map); System.out.println("HTML >> " + resp); } } } // 许愿瓶 // url = "https://pirate-api.hortor002.com/game/annual/open-lucky-box"; // dataMap = new HashMap<String, String>(); // dataMap.put("uid", uid); // dataMap.put("useFree", "false"); // dataMap.put("isWxGame", "true"); // dataMap.put("t", t); // dataMap.put("secret", secret); // param = formatUrlMap(dataMap, false, false); // System.out.println("param >> " + param); // param = param.replaceAll("&", ""); //把&去掉 // sign = md5(param); // System.out.println("sign >> " + sign); // map = new HashMap<String, Object>(); // map.put("uid", uid); // map.put("useFree", "false"); // map.put("isWxGame", "true"); // map.put("t", t); // map.put("secret", secret); // map.put("sign", sign); // resp = relynSpider.postWechat(url, map); // System.out.println("HTML >> " + resp); // 建造 for (int building = 0; building < 5; building++) { for (int level = 1; level < 6; level++) { url = "https://pirate-api.hortor002.com/game/island/build"; dataMap = new HashMap<String, String>(); dataMap.put("uid", uid); dataMap.put("island", island); dataMap.put("building", String.valueOf(building)); dataMap.put("level", String.valueOf(level)); dataMap.put("t", t); dataMap.put("secret", secret); param = RelynSpider.formatUrlMap(dataMap, false, false); System.out.println("param >> " + param); param = param.replaceAll("&", ""); // 把&去掉 sign = RelynSpider.md5(param); System.out.println("sign >> " + sign); map = new HashMap<String, Object>(); map.put("uid", uid); map.put("island", island); map.put("building", building); map.put("level", level); map.put("t", t); map.put("secret", secret); map.put("sign", sign); resp = relynSpider.postWechat(url, map); System.out.println("HTML >> " + resp); } } } public static void main(String[] args) { // TODO Auto-generated method stub // 下面这三个参数,抓包下就能看到啦 encryptedCode = "; uid = ""; userId = ""; island = ""; //这个是目前要建的岛屿序号,从0开始的 start(encryptedCode, uid, userId, island); }