Js逆向--新版Steam登錄之Protobuf協(xié)議數(shù)據(jù)解析

前言

Steam游戲平臺在今年三四月份更新了登錄協(xié)議岂却,放棄了原有的簡單RSA加密健田,數(shù)據(jù)傳輸格式改成了Protobuf協(xié)議,難度相比之前大了許多予颤,主要還是對于Protobuf協(xié)議不熟悉旅敷,最近看了之前RSA加密相關(guān)視頻凶硅,懷著熱血想小試牛刀一下,結(jié)果當(dāng)看到返回的數(shù)據(jù)格式時(shí)扫皱,一下子就傻眼了足绅,經(jīng)過了5天的研究調(diào)試,期間差點(diǎn)放棄韩脑,好在最后還是被我逆向出來了

目標(biāo)

看過新版steam請求的都知道氢妈,來到登錄界面,輸入賬號密碼后點(diǎn)擊登錄段多,會出現(xiàn)一個(gè)get請求首量,查看這個(gè)請求的負(fù)載發(fā)現(xiàn)有兩個(gè)參數(shù),origin自不用說是個(gè)固定的进苍,可以看出來input_protobuf_encoded是個(gè)被加密過的


image.png

image.png

同時(shí)查看響應(yīng)的數(shù)據(jù)加缘,掐指一算,是一串有亂碼的字符串觉啊,看來這個(gè)響應(yīng)數(shù)據(jù)也是被加密過的(準(zhǔn)確的說是利用protobuf協(xié)議序列化過)


image.png

所以本節(jié)主要內(nèi)容就是對請求參數(shù)中加密的input_protobuf_encoded進(jìn)行解析拣宏,以及對響應(yīng)的數(shù)據(jù)進(jìn)行解析。

protobuf數(shù)據(jù)格式

引入正題杠人,protobuf是什么勋乾,具體百度一下你就知道,簡單來說protobuf是一種Google提供的高效的協(xié)議數(shù)據(jù)交換格式嗡善,就像JSON一樣辑莫,有固定的格式,正向開發(fā)中需要編寫罩引。proto 文件來秒數(shù)這個(gè)數(shù)據(jù)具體都有什么信息各吨,逆向沒有這個(gè)文件,就只能根據(jù)值盲猜了袁铐,我為什么知道這個(gè)是protobuf數(shù)據(jù)格式揭蜒,沒人天生知道,經(jīng)過這幾天的研究才知道大概是什么數(shù)據(jù)

那如何使用protocol buffers昭躺?

開發(fā)者需要先編寫proto文件忌锯,在proto文件中編寫預(yù)期的數(shù)據(jù)類型、數(shù)據(jù)字段领炫、默認(rèn)值等
然后,通過編譯器生成张咳,編程語言對應(yīng)的開發(fā)包帝洪!開發(fā)時(shí)調(diào)開發(fā)包中的對應(yīng)方法進(jìn)行序列化和反序列化似舵。


image.png
Protobuf 實(shí)現(xiàn)基本過程

1、編寫 .proto 文件
2葱峡、將 .proto 文件編譯成對應(yīng)編程語言的包
3砚哗、將包導(dǎo)入,通過代碼實(shí)現(xiàn) .proto 文件的序列化砰奕,并將序列化后的內(nèi)容保存到 .bin 文件中蛛芥,序列化后的數(shù)據(jù)可讀性極差
Protobuf 序列化完成,此時(shí)就可以在網(wǎng)絡(luò)間進(jìn)行傳輸军援,接收端若想還原為可讀數(shù)據(jù)仅淑,則需進(jìn)行反序列化操作。
既然如此胸哥,我們可以簡單的實(shí)現(xiàn)以上過程
1涯竟、創(chuàng)建.proto文件,編寫簡單的數(shù)據(jù)

image.png

2空厌、將.proto編譯成.js文件庐船,至于編譯器網(wǎng)上很多教程,我這里提供一個(gè)編譯器下載地址:https://github.com/protocolbuffers/protobuf/releases/
安裝完后嘲更,對.proto進(jìn)行編譯,定位到文件所在目錄,執(zhí)行如下命令筐钟,生產(chǎn)對應(yīng)_pb.js文件

protoc --proto_path=.\ [目標(biāo)文件名].proto --js_out=import_style=commonjs:. --grpc-web_out=import_style=commonjs,mode=grpcwebtext:.
image.png

大致查看了解一下結(jié)構(gòu)

image.png

image.png

image.png

大概的操作就是以我們自己編寫的.proto文件中的數(shù)據(jù)格式為準(zhǔn),將對應(yīng)格式的數(shù)據(jù)進(jìn)行二進(jìn)制序列化或者反序列protobuf格式的二進(jìn)制數(shù)據(jù)為.proto文件定義的對象的格式赋朦。
(這里可以多注意一下serializeBinary這個(gè)方法名盗棵,方法體的代碼寫法,后面會用到)

3北发、使用生成的xx_pb.js文件可以用來干嘛纹因?

  1. 將對象數(shù)據(jù)序列化成二進(jìn)制protobuf格式的亂碼數(shù)據(jù)
    生成的xx_pb.js中有一個(gè)初始化代碼,先進(jìn)行初始化琳拨,傳入的參數(shù)是個(gè)數(shù)組瞭恰,每個(gè)數(shù)組的索引位置對應(yīng).proto中一個(gè)唯一的序號


    image.png

    image.png

    上面生成的e 就是二進(jìn)制protobuf格式的亂碼數(shù)據(jù)

  2. 解析二進(jìn)制protobuf格式的亂碼數(shù)據(jù)
    (這里我不使用生成的.js文件來解析,因?yàn)槲易罱K目的是用python爬蟲狱庇,所以我打算使用.proto生成對應(yīng)的.py文件來進(jìn)行解析)
    執(zhí)行類似上面的命令,生成對應(yīng)的_pb2.py文件


    image.png

    image.png

這代碼我是看不懂的惊畏,但是用還是會用的。。
現(xiàn)在我們可以使用hhh_pb2.py中的代碼來解析proto_buf了。首先岔乔,我們需要導(dǎo)入生成的代碼:

import hhh_pb2

然后篓吁,創(chuàng)建一個(gè)Body實(shí)例,并使用ParseFormString()方法解析:

body = hhh_pb2.Body()
body.ParseFromString(proto_buf_data)

在上面的代碼中迫横,proto_buf_data是一個(gè)包含了proto_buf數(shù)組的字節(jié)流酷窥。
一旦我們成功地解析了proto_buf數(shù)據(jù)继找,我們就可以通過訪問Body實(shí)例的字段來獲取數(shù)據(jù)了口猜。例如负溪,我們可以獲取name字段的值

name = body.name

此外,對于repeated類型的字段济炎,我們可以使用類似于列表的方法來訪問他們的值:

for hobby in body.hobbies:
  print(hobby)

這樣就完成了對proto_buf數(shù)據(jù)的解析

逆向解密請求參數(shù)input_protobuf_encoded

第一步根據(jù)input_protobuf_encoded名字找到對應(yīng)加密的js文件川抡,并且定位到input_protobuf_encoded賦值的地方,這里就不一一調(diào)試须尚,網(wǎng)上有很多教學(xué)崖堤,我這里直接定位到關(guān)鍵代碼


image.png

可以看到執(zhí)行完a = r.JQ(o)后生成的a值和請求參數(shù)對比一下發(fā)現(xiàn)就是加密后的數(shù)據(jù),后面d.params.input_protobuf_encoded = a 這樣的代碼也證明了這里就是需要逆向的關(guān)鍵代碼耐床,鼠標(biāo)移到s密幔,發(fā)現(xiàn)這個(gè)值是請求的基礎(chǔ)url,在這里并沒有什么用處可以忽略咙咽。

第二步老玛,創(chuàng)建js文件,將關(guān)鍵代碼復(fù)制進(jìn)去


image.png

運(yùn)行報(bào)錯(cuò) n is not defined钧敞,鼠標(biāo)移動(dòng)到n.SerializeBody蜡豹,定位到主要方法


image.png

image.png

將代碼拷貝到j(luò)s,改寫一下代碼溉苛,在運(yùn)行出現(xiàn)報(bào)錯(cuò)镜廉,提示沒有serializeBinary這個(gè)方法,
image.png

老規(guī)矩愚战,進(jìn)入serializeBinary對應(yīng)的方法


image.png

image.png

將代碼再拷貝到j(luò)s運(yùn)行娇唯,發(fā)現(xiàn)還是繼續(xù)報(bào)錯(cuò),根據(jù)我們一步一步補(bǔ)環(huán)境寂玲,發(fā)現(xiàn)非常麻煩塔插,可能到最后還是毫無頭緒。
這時(shí)候我們不妨換個(gè)思路拓哟,通過請求的響應(yīng)數(shù)據(jù)可以看出想许,該請求是使用protobuf協(xié)議來傳輸數(shù)據(jù)的,那么只有在響應(yīng)返回的數(shù)據(jù)中才進(jìn)行處理嗎断序?會不會在請求的參數(shù)中也進(jìn)行了protobuf處理流纹?
有了這個(gè)思路,我們觀察一下補(bǔ)寫js代碼時(shí)出現(xiàn)的代碼
image.png

這個(gè)代碼中的方法serializeBinary以及里面的實(shí)現(xiàn)是不是跟上面我們在講protobuf協(xié)議的時(shí)候生成的_pb.js代碼中的serializeBinary很相似违诗?
在觀察有一個(gè)這樣的代碼漱凝,可以大概知道這個(gè)c類主要就是對account_name這個(gè)字段進(jìn)行處理
image.png

看到這些代碼,我腦海里有個(gè)想法诸迟,這個(gè)請求對請求參數(shù)的處理是不是將用戶名先通過protobuf協(xié)議處理了一下茸炒,然后再用base64加密呢愕乎??
有了這個(gè)思路扣典,我們試著根據(jù)上面的代碼編寫一下用戶名對應(yīng)的accountName.proto文件并編譯成js


image.png

image.png

結(jié)合上面我們拷貝到j(luò)s中的SerializeBody方法妆毕,進(jìn)行改寫
先初始化將用戶名數(shù)組傳入慎玖,然后調(diào)用編譯生成的serializeBinary方法
image.png

運(yùn)行發(fā)現(xiàn)e有結(jié)果了贮尖!之后就是普通的代碼改寫運(yùn)行發(fā)現(xiàn)生成了一串?dāng)?shù)據(jù),對比一下就是我們想要的數(shù)據(jù)
image.png

protobuf協(xié)議反序列化字節(jié)流數(shù)據(jù)

首先趁怔,根據(jù)上面生成的參數(shù)發(fā)起請求湿硝,得到返回的序列化過的protobuf字節(jié)流數(shù)據(jù)。
因?yàn)槟嫦驔]有proto這個(gè)文件润努,就只能根據(jù)值盲猜了关斜,那怎么獲取值呢,查資料我找到了兩種比較好的方法

  1. 到github搜索blackboxprotobuf
    下載blackboxprotobuf-master.zip铺浇,解壓將blackboxprotobuf拖入到python庫中
    image.png

導(dǎo)入blackboxprotobuf痢畜,調(diào)用decode_message方法解析


image.png

打印出這樣的數(shù)據(jù)


image.png

根據(jù)這樣的數(shù)據(jù)結(jié)構(gòu)找找有沒有相關(guān)的代碼,果然被我找到了鳍侣,可以根據(jù)這里定義的類型更加容易編寫.proto文件
image.png

image.png

編譯成_pb2.py


image.png

導(dǎo)入RSAPublicKey_pb2調(diào)用解析數(shù)據(jù)
image.png

image.png

這樣一來就成功反序列化得到我們需要的數(shù)據(jù)啦~~
2)除了上面查看字節(jié)流數(shù)據(jù)的方法外丁稀,還可以通過將字節(jié)流數(shù)據(jù)保存成.bin文件,在使用protoc --decode_raw < v1.bin命令來生成
image.png

image.png

小結(jié)

到此倚聚,這個(gè)請求該解析的都解析了线衫,其實(shí)思路并不難,最大難點(diǎn)是對protobuf協(xié)議的不熟悉惑折,我們了解了協(xié)議后授账,就能知道該網(wǎng)站的處理方法是先對數(shù)據(jù)進(jìn)行protobuf協(xié)議序列化,之后可能是在對序列化數(shù)據(jù)在加密或者甚至就沒加密直接返回惨驶。
到這里本節(jié)結(jié)束白热,算是給自己這幾天研究的結(jié)果做一個(gè)總結(jié)記錄!
(可能講的有點(diǎn)亂粗卜,需要相關(guān)的代碼可以聯(lián)系我哦)

這里先對a = r.JQ(o)這行進(jìn)行改寫屋确,鼠標(biāo)移動(dòng)到r.JQ,定位到對應(yīng)的方法


image.png

image.png

復(fù)制到j(luò)s休建,改寫一下代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乍恐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子测砂,更是在濱河造成了極大的恐慌茵烈,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砌些,死亡現(xiàn)場離奇詭異呜投,居然都是意外死亡加匈,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門仑荐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雕拼,“玉大人,你說我怎么就攤上這事粘招∩犊埽” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵洒扎,是天一觀的道長辑甜。 經(jīng)常有香客問我,道長袍冷,這世上最難降的妖魔是什么磷醋? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮胡诗,結(jié)果婚禮上邓线,老公的妹妹穿的比我還像新娘。我一直安慰自己煌恢,他們只是感情好骇陈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著症虑,像睡著了一般缩歪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谍憔,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天匪蝙,我揣著相機(jī)與錄音,去河邊找鬼习贫。 笑死逛球,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的苫昌。 我是一名探鬼主播颤绕,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼祟身!你這毒婦竟也來了奥务?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤袜硫,失蹤者是張志新(化名)和其女友劉穎氯葬,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體婉陷,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帚称,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年官研,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闯睹。...
    茶點(diǎn)故事閱讀 40,015評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡戏羽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出楼吃,到底是詐尸還是另有隱情始花,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布所刀,位于F島的核電站衙荐,受9級特大地震影響捞挥,放射性物質(zhì)發(fā)生泄漏浮创。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一砌函、第九天 我趴在偏房一處隱蔽的房頂上張望斩披。 院中可真熱鬧,春花似錦讹俊、人聲如沸垦沉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽厕倍。三九已至,卻和暖如春贩疙,著一層夾襖步出監(jiān)牢的瞬間讹弯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工这溅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留组民,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓悲靴,卻偏偏與公主長得像臭胜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子癞尚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容