【思路】
很早就想做一个多看的自动签到,不过抓包后发现,每次签到时,除了固定的 header 信息,还要带上2个变动的参数“_t”和“_c”。前者是时间戳,而后者一直没弄懂。
直到这几天学会了反编译多看apk,从反编译后的混淆代码中,可以找到了以下代码:
public static String[] genCsrfCode(){ int timeMillis = (int)(System.currentTimeMillis() / 1000L); String[] arrayOfString = (ReaderEnv.get().getDeviceId() + '&' + timeMillis).split(""); int i = 1; int j = 0; while (i < arrayOfString.length) { j = generate(j, arrayOfString[i]); i++; } return new String[] { "_t", String.valueOf(timeMillis), "_c", String.valueOf(j) }; } private int generate(int paramInt, String paramString){ return (paramInt * 131 + paramString.getBytes()[0]) % 65536; }
从代码中可以看出,header 中的 deviceId,和 _t 时间戳,共同参与生成了 _c 参数。
照着这段代码,写了个 php 版的自动签到脚本。丢进 PHP 虚拟空间,用 Cron 功能每天运行下就可以了。
由于担心哪天空间或脚本出问题,所以又添加了 sever酱 sc.ftqq.com/3.version 的服务。自动将签到结果发送到我的微信中。不过这个就不在给出的代码中贴出了,有需要的自行添加吧。
【使用步骤】
①在手机(安卓)上安装PacketCapture应用,打开其抓包功能。
②打开多看。
③回到PacketCapture,查看这次抓包记录。
④找到含有Cookie的header。
⑤把Cookie信息按代码中的提示,放入代码中。
⑥把Cookie信息中的device_id的值,按按代码中的提示,放入代码中。
⑦把代码放入PHP空间,用Cron定时运行。
需要替换两处地方(部分敏感信息打码了):
$r_header['Cookie'] = 'device_id=****************;app_id=DkReader.Android;build=********;channel=VSZUVB;user_type=1;device_hash=****************;token=****************;user_id=********;'; $device_id = '****************';
【多看自动签到,PHP版代码】
<?php /** * Atuhor: Wizos * PubDate: 2016-11-30 * Version: 1.0 * description: 这是一个多看阅读的自动签到脚本,具体的说明见文章: */ $r_header['Cookie'] = '这里是你的 Cookie'; $r_header['Accept-Encoding'] = 'gzip,deflate'; $r_header['User-Agent'] = 'Dalvik/2.1.0 (Linux; U; Android 5.1; MX5 Build/LMY47I)'; // _t=1478918449&_c=10614 (一组实际的数据,作为参考) function get_csrf_params () { $device_id = '这里是你的 Device_id'; $time_sec = time(); $array_of_str = get_array( $device_id.'&'.$time_sec ); $i = 0; $csrf_code = 0; $size = count( $array_of_str ); while ( $i < $size ) { $csrf_code = generate( $csrf_code, $array_of_str[$i] ); $i++; } $param = "_t=".$time_sec."&_c=".$csrf_code; echo '参数为:'.$param.'<br>'; return $param; } function generate ( $paramInt, $paramString ) { $by = get_bytes( $paramString ); return ($paramInt * 131 + $by[0]) % 65536; } function get_bytes($string) { $bytes = array(); for($i = 0; $i < strlen($string); $i++){ $bytes[] = ord($string[$i]); } return $bytes; } function get_array ( $str ) { $arr = array(); for($i=0;$i<strlen($str);$i++){ $arr[$i] = $str[$i]; } return $arr; } function post( $url, $params ) { $curl = curl_init();//初始化curl模块 curl_setopt($curl, CURLOPT_URL, $url );//登录提交的地址 curl_setopt($curl, CURLOPT_HEADER, 0);//如果你想把一个头包含在输出中,设置这个选项为一个非零值 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);//设置不输出在浏览器上 curl_setopt($curl, CURLOPT_COOKIE, $GLOBALS['r_header']["Cookie"] ); //设置Cookie信息保存在指定的文件中 curl_setopt($curl, CURLOPT_HTTPHEADER, $GLOBALS['r_header'] ); curl_setopt($curl, CURLOPT_POST, 1);//post方式提交 curl_setopt($curl, CURLOPT_POSTFIELDS, $params );//要提交的信息 if (preg_match('/^https/',$url)){ //curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1 ); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0 ); } $data = curl_exec($curl);//执行cURL $curl_errno = curl_errno($curl); curl_close($curl);//关闭cURL资源,并且释放系统资源 if($curl_errno>0){ return 'error'; }else{ return $data; } } header('Content-Type: text/html; charset=utf-8') ; $post_params = get_csrf_params(); $sign_in_msg = post( 'https://www.duokan.com/checkin/v0/checkin' , $post_params ); echo '<hr>'; $response = json_decode($sign_in_msg); if ( $response->{'result'} == 0 ) { echo "签到成功:".$sign_in_msg; }else{ echo "签到失败:".$sign_in_msg; } ?>