前言
今天本著學(xué)習(xí)研究的態(tài)度,下載了一個(gè)滴答清單PC pj版局蚀,發(fā)布日期大概是19年4月左右麦锯。
下載之后登錄時(shí)卻遇到了問(wèn)題,輸完賬號(hào)密碼點(diǎn)擊登錄琅绅,然后就會(huì)提示Login_OutDate扶欣,大概就是說(shuō)用戶(hù)不是VIP了,不能用,請(qǐng)重新登錄
由于比較好奇為什么之前能用料祠,現(xiàn)在不能用了骆捧,于是逆了一下代碼,然后就有了這篇文章髓绽,成功的繞過(guò)了登錄后彈窗的問(wèn)題敛苇,以及無(wú)法同步的限制
正文
首先根據(jù)關(guān)鍵字定位到彈窗代碼
可以從上圖看到,程序彈窗之后就會(huì)關(guān)閉當(dāng)前窗體顺呕,重置界面登錄狀態(tài)枫攀,顯示登錄窗體,那么我們就可以通過(guò)return大法很輕松的讓程序不退出登錄并繼續(xù)執(zhí)行
進(jìn)行修改后株茶,我們繼續(xù)分析函數(shù)關(guān)系来涨,找到上級(jí)調(diào)用,看看還有沒(méi)有其他檢測(cè)
可以看到启盛,上面其實(shí)也是對(duì)當(dāng)前登錄的用戶(hù)信息進(jìn)行了一個(gè)重置的操作的蹦掐,所以這邊也是要繼續(xù)return掉的
保險(xiǎn)起見(jiàn)繼續(xù)回溯,看上級(jí)調(diào)用
從這里可以看出來(lái)僵闯,程序請(qǐng)求了滴答清單的API接口來(lái)獲取用戶(hù)信息卧抗,如果檢測(cè)到用戶(hù)非法,就執(zhí)行剛剛我們找到的那一系列函數(shù)進(jìn)行登出操作棍厂。
那么做到這一步之后颗味,就解決了PC端登錄秒退的問(wèn)題,用戶(hù)已經(jīng)可以正常本地使用原破解版的所有功能了牺弹,但目前還不能同步,會(huì)提示網(wǎng)絡(luò)錯(cuò)誤
所以我們繼續(xù)看為什么會(huì)走到:response.StatusCode == HttpStatusCode.Unauthorized时呀,能否通過(guò)修改判斷邏輯實(shí)現(xiàn)數(shù)據(jù)同步
為了方便大家理解张漂,我把上面那張圖中所在函數(shù)的關(guān)鍵邏輯貼出來(lái)
嫌亂的可以跳過(guò)這部分代碼,我一會(huì)還會(huì)用文字解釋
HttpClient httpClient = ProxyHelper.GetHttpClient();
httpClient.DefaultRequestHeaders.Add("Authorization", "OAuth " + **auth**);
httpClient.DefaultRequestHeaders.Add("User-Agent", "TickTickClient/1.0");
httpClient.DefaultRequestHeaders.Add("x-device", Utils.GetDeviceInfo());
string domain = BaseUrl.GetDomain();
string uriString;
if (!**fulluri**)
{
uriString = domain + **api**;
}
else
{
uriString = **api**;
}
string mode2 = **mode**;
if (!(mode2 == "POST"))
{
if (!(mode2 == "GET"))
{
if (!(mode2 == "PUT"))
{
if (mode2 == "DELETE")
{
response = httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Delete, new Uri(uriString))
{
Content = new StringContent(**content**, Encoding.UTF8, "application/json")
}).Result;
}
}
else
{
response = httpClient.PutAsync(new Uri(uriString), new StringContent(**content**, Encoding.UTF8, "application/json")).Result;
}
}
else
{
response = httpClient.GetAsync(new Uri(uriString)).Result;
}
}
else if (**paramList** == null || **paramList**.Count == 0)
{
response = httpClient.PostAsync(new Uri(uriString), new StringContent(**content**, Encoding.UTF8, "application/json")).Result;
}
else
{
response = httpClient.PostAsync(new Uri(uriString), new FormUrlEncodedContent(**paramList**)).Result;
}
if (response != null && (response.StatusCode == HttpStatusCode.OK | **isNeedErrorReturn**))
{
responseReturn = response.Content.ReadAsStringAsync().Result;
if (App.ProExpiredSyncError)
{
App.ProExpiredSyncError = false;
}
}
else if (response != null && response.StatusCode == HttpStatusCode.InternalServerError)
{
responseReturn = response.Content.ReadAsStringAsync().Result;
if (!string.IsNullOrEmpty(responseReturn))
{
NetWork.HandleApiError(responseReturn);
}
}
else if (response != null && response.StatusCode == HttpStatusCode.Unauthorized)
{
Utils.TokenOutDate();
}
這段代碼大概說(shuō)了個(gè)啥呢谨娜?其實(shí)邏輯很簡(jiǎn)單航攒,就下面4個(gè)步驟:
- 獲取當(dāng)前設(shè)備信息
- 獲取需要同步的數(shù)據(jù)(比如新增、刪除趴梢、修改待辦事項(xiàng)這些)
- 將需要同步的數(shù)據(jù)和當(dāng)前設(shè)備信息發(fā)送到滴答清單的遠(yuǎn)程API接口
- 根據(jù)遠(yuǎn)程API返回判斷是否同步成功
總的來(lái)說(shuō)漠畜,這些邏輯是通過(guò)傳參數(shù)到服務(wù)端進(jìn)行校驗(yàn),本地并沒(méi)有做會(huì)員狀態(tài)檢測(cè)坞靶,直接調(diào)用的服務(wù)端API接口
但憔狞!滴答清單有一個(gè)比較特殊的地方,他的手機(jī)端數(shù)據(jù)是可以相互同步的
也就是說(shuō)彰阴,我們或許可以通過(guò)修改電腦端發(fā)出的請(qǐng)求瘾敢,使服務(wù)端API認(rèn)為我們是一個(gè)手機(jī)APP,這樣我們就可以繞過(guò)檢測(cè)直接同步了
通過(guò)手機(jī)APP抓包對(duì)比,我發(fā)現(xiàn)只需要修改:
httpClient.DefaultRequestHeaders.Add("x-device", Utils.GetDeviceInfo());
為:
httpClient.DefaultRequestHeaders.Add("x-device", “手機(jī)端UA”);
即可模擬成手機(jī)請(qǐng)求
修改的過(guò)程中我發(fā)現(xiàn)其實(shí)原破解作者也是相同的思路簇抵,他修改了Utils里的GetDeviceInfo函數(shù)庆杜,強(qiáng)制返回一個(gè)iPad的UA,按理說(shuō)是可以同步的(并且前幾個(gè)月確實(shí)能正常使用)
那么我可以做出合理推測(cè)碟摆,原作者發(fā)布破解版本后晃财,被大家廣泛使用,最后滴答清單官方團(tuán)隊(duì)取得了破解樣本典蜕,進(jìn)行分析后断盛,對(duì)該UA進(jìn)行了拉黑處理
也就是說(shuō)——目前網(wǎng)上流傳的那些破解版本沒(méi)準(zhǔn)都是出自一人之手。嘉裤。所以一個(gè)UA封掉之后全部不能用了
總而言之郑临,通過(guò)修改UA的值,即可繞過(guò)服務(wù)端API檢測(cè)屑宠,實(shí)現(xiàn)數(shù)據(jù)同步
后記
回顧了一下整個(gè)流程厢洞,其實(shí)官方應(yīng)該是拉黑了破解版的UA,所以只要換掉UA典奉,應(yīng)該就不會(huì)出現(xiàn)異常檢測(cè)了躺翻,也就是說(shuō)不需要去在函數(shù)內(nèi)做return。
博客文章遷移: 2020-01-12 01:23