【思路】
很早就想做一个多看的自动签到,不过抓包后发现,每次签到时,除了固定的 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;
}
?>