<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    Typora解密之跳動的二進制

    VSole2022-05-18 16:55:00

    磨刀霍霍 :準備工作

    開發環境識別

    用IDA打開 Typora.exe (不建議,可能是我電腦問題,IDA分析了三四個小時),打開后發現程序中有 electron ,V8字樣,由于前幾天剛好分析了一個IE漏洞,由V8聯想到 JavaScript引擎,此時猜測與JS語言有關。

    打開程序目錄,查看一下有沒有JS代碼,一番查找,看到了asar文件以及node字樣,感覺有些眼熟哪里見過。問一下度娘,百度搜索asar,electron,nodemodules

    不搜不知道,一搜嚇一跳,原來這是使用 NodeJs的electron框架開發的桌面應用,JS也能寫桌面程序了。

    繼續搜索相關資料,得到以下信息:

    1.electron 使用了谷歌的 V8引擎以及渲染引擎(意思是這種程序跟個瀏覽器差不多唄)

    2.electron 有主進程與渲染進程 ,通過IPC交換信息,渲染進程只負責渲染(難怪我附加調試有好幾個進程。。)

    3.Typora.exe是electron框架,基本與開發者的代碼無關(修改框架復雜度太高,一般人不會去動,所以別去逆向它了)

    4.查看目錄發現,在app.asar.unpacked中發現了一個 main.node ,看名字很奇怪,.node文件是啥東西

    5.app.asar是打包的JS代碼,并且只是簡單的打包,沒有任何加密措施,且electron也沒有代碼保護措施(圈起來要考)

    根據第五條信息,筆者嘗試使用工具對asar進行解包,解包失敗不知道什么原因(或許必須使用NodeJS自帶的解包工具?但是解包也是加密文件,我又懶得下載nodejs,需要的時候再解吧),放進010editor查看,得到文件名與一些密文,此時陷入了僵局。

    嘗試調試

    打開typora進程,x64dbg附加,查看有沒有有用的信息(剛開始我不知道這個是NodeJS開發,想著通過注冊窗口跟蹤程序流程,好家伙差點就逆到引擎去了),發現了有好幾個進程,后面命令行參數可以看到渲染gpu等關鍵字,并且目錄參數指向了app.asar。

    根據前面得到的信息,這些進程都是由主進程創建的,程序邏輯是由主進程處理,那么附加主進程看一下(沒參數的那個)

    看到了主進程加載了main.node模塊,什么.node也能當dll加載 ? 或許它本來就是一個dll呢(也不排除加殼后,手動加載的情況)

    那么使用PE工具查一下,VS2017編譯的64位DLL。

    梅開二度 :邏輯分析

    到這一步,已知信息:

    1.JS文件被加密

    2.框架為electron

    3.框架會加載main.node模塊

    4.解析JS腳本的是V8引擎

    5.c++支持node api進行開發

    根據我們的已知信息,來對程序的整體邏輯進行一個簡單的分析。

    1.框架對代碼無保護且修改框架難度過高,V8引擎不支持解析加密的JS代碼,那么JS代碼如何運行?

    站在一個開發者的角度,我可能會想到由框架加載我的解密代碼,把js代碼解密后送到js引擎去執行就可以了

    2.那么解密代碼放在哪里合適呢?

    既然框架被編譯為二進制了,且根據之前的分析,妥妥的c++開發,想要最簡單的方法實現解密,加載同樣為c/c++編譯的二進制代碼即可。在Windows平臺上,想要加載代碼執行,也就剩動態鏈接庫了。由此可以推測,之前找到的main.node,可能就是解密模塊。

    邏輯總結

    • 框架加載解密模塊
    • 解密模塊對app.asar進行解密(解密后會不會把文件寫出來呢,如果寫出來可以直接拷走。。)
    • 解密后的代碼送入JS引擎執行
    • 另外的邏輯 :由解密模塊解密app.asar的xxx.js代碼,xxx.js代碼執行后,由它來負責解密剩下的js代碼并執行,可以提高破解難度

    精益求精 :main.node分析

    1.根據之前的推測,main.node負責解密,按照程序員開發習慣,Ctrl CV實現,也就是使用公開的一些算法

    2.IDA加載main.node,按照逆向慣例,先搜索一波字符串

    此時看到了buffer,base64,app.asar等關鍵字。猜測一下,app.asar加載到buffer然后進行base64解密。 

    3.繼續開展搜索工作,base64未免太過簡單了吧,使用FindCrypt3插件 ,搜索一下算法常量吧。

    此時找到了AES的算法常量,前兩個是重復的,可能是插件問題。

    4.好的,現在面臨一個問題,我不懂算法,怎么解密。。。只能去問度娘了,搜索一下AES加密解密原理與 C 實現代碼。

    5.根據搜索得知:

    • AES使用最后那個常量數組進行解密
    • AES有五種加密模式,常用的為ECB CBC模式
    • 根據AES密鑰長度,有不同的加密輪數(不是很懂哈。。)

    6.對解密常量進行交叉引用跟蹤,找到這個函數以后,繼續對函數進行交叉引用跟蹤。

    大概經過三四次的跟蹤,發現了這個函數,在這個函數里F5查看反編譯代碼,發現了app.asar字符串的引用。

    7.此時進行推測,這個函數加載了app.asar的內容,并且調用 SUB_180003E40進行解密。

    8.跟進SUB_180003E40 進行查看 ,此時發現了base64字符串的引用,推測對buffer進行了base64解密。

    9.看到很多不認識的API,百度搜索得知,這是Node API,簡單去看一下函數功能http://nodejs.cn/api/n-api.html#napi_call_function

    NAPI_EXTERN napi_status napi_call_function(napi_env env,            //環境                                           napi_value recv,         //名為global的值                                           napi_value func,            //要調用的javascript函數                                           size_t argc,                //JavaScript函數的參數個數  類似argc                                           const napi_value* argv,  //JavaScript函數的參數數組  類似argv                                           napi_value* result);     //返回的JavaScript對象
    

    10.根據文檔得到的信息,參照這一部分Node API,得到了如下信息(猜測調用了此函數)筆者對這語法難以理解,程序的目的是把對象進行base64編碼?但是看這代碼,base64也沒有被當作參數傳遞進去

    Buffer.from( object, encoding )object:此參數可以包含字符串,緩沖區,數組或arrayBuffer。encoding:如果對象是字符串,則用于指定其編碼。它是可選參數。其默認值為utf8。 Buffer.from(string[, encoding]):返回一個被 string 的值初始化的新的 Buffer 實例
    

    11.暫時先不管node api的語法與功能,繼續往下看。

    看到了這部分的函數調用,進入查看,發現與 C實現AES算法結構相似,推測這部分為AES解密。

    分析總結

    根據目前的分析,得到如下信息

    • main.node模塊使用node api 進行js函數調用
    • main.node模塊使用了AES解密算法(模式未知)

    到了這一步,想要繼續破解,首先要得到js代碼,有兩個辦法以及面臨的問題。

    1.分析算法,找到密鑰,如果是CBC模式,還需要找到IV ,之后使用解密算法,解密app.asar的js代碼

    2.分析程序執行流程,找到解密后的緩沖區,直接拷走,得到徹底解密后的js代碼。

     

    面臨的問題:

    • nodejs語法不懂,這些api調用的具體js函數不清晰
    • AES解密流程不熟悉,找到密鑰或者iv的難度較高(通過加密輪數判斷密鑰長度,通過算法部分判斷加密模式,并找到相關數據)
    • 就算你找到解密AES的辦法,它會不會還有別的加密措施與防護措施,例如密鑰需經過hash摘要,文件完整性校驗等(如果還有加密保護措施,那還得繼續分析別的算法,一步一步還原,對于算法不熟悉的人時間成本太大了)

    大海撈針 :尋找JS代碼

    1.根據之前的分析,我選擇第二種獲得js代碼的辦法,分析程序執行流程得到解密后的 JS代碼。

    2.分析解密前的 js函數調用,由之前的分析得知,參數有兩個,在V27的位置,V27是由參數 a3 +8 得來的,動態調式一波。

    3.x64dbg打開typora.exe,下一個dll斷點,根據之前分析,他是動態加載的(多打了個a 懶得換圖了)

    4.斷點設置完成后,斷在loadlibrary,進入模塊入口后,去IDA計算偏移,定位到前面分析的函數位置。

    對了,記得使用x64dbg自帶的 PEB隱藏功能,并忽略所有異常,這個模塊有簡單的反調試手段(查看導入表可知,太過簡單不分析反調試手段了)

    定位函數位置,直接看后4位即可,同樣為模塊偏移 674A的位置。

    5.下斷后查看decrypt(命名一下方便)函數的參數,x64架構下,函數參數為 rcx rdx r8 r9 rsp+0x20

    前四個從左到右,超過四個則入棧,rsp+0x20為起始地址,詳情可參考微軟x64調用約定。

     

    6.r8 = a3 查看 *(a3 + 8)的值, ,這個值為之前分析的 v27 地址,也就是argv 繼續查看指針指向內容。

    現在得到了buffer.from js函數的兩個參數 ,第一個像是密文,第二個沒看出來,不是預料中的base64,所以之前的推斷貌似是錯的?

    7.關注一下這兩個地址 0000079908482119 00000799083CFEA5 在調用完js函數會有什么改變,直接來到調用的位置,調試器同步來到這個位置。

    來到這個位置再次確認參數,第五個參數為 rsp+20,也就是rax的值,rax為argv,進入內存查看得到前面同樣的地址,也就是 (a3 + 8),步過這個函數,查看對參數的改變。

    8.執行完后查看剛才記錄的位置,好的好的,耍我呢,啥都沒變,并且后續也沒調用相關數據(或許是最后一個參數返回了一個對象,忘記看了,如果返回的話應該是密文相關的東西,并且放到了某個數據結構中,所以在IDA中沒看到直接使用的行為)

    繼續分析,到了AES解密代碼部分,既然是解密,那肯定得把密文的緩沖區拿過來吧。

    首先看到一串16進制的賦值,v46開頭的數組 剛好32個字節,也就是256bit有點像是AES-256的樣子了。然后看到申請了 32字節的內存,v32

    之后調用了 sub_18000B060函數,對v46 與 v32進行操作, 目測參數為 (目標地址,源地址,大小)

    進入 sub_18000B060函數查看,一大堆運算,根本不想看,根據之前的推測,可能是作者感覺直接把密鑰放在程序中有些不妥,所以對密鑰進行一個類似于解密或hash運算的工作(不展開分析了)

    9.繼續分析

    可以看到sub_180007000 函數 ,參數v45 IDA提示我是一個 char[256]的數組,v32為32字節的地址,v10為一串神秘數據。

    可以得到一個結論,在經過 v46的一系列運算,得到了一個同樣大小 32字節的數據,再把數據 與 v10神秘數據進行操作,放入v45的256字節的數組中(好家伙 這是密鑰嗎 搞這么復雜)

    跟進sub_180007000 查看, 把v10放到了 v45數組的0xF0的位置

    之后調用了sub_180007800函數對自己的PE文件有些操作,簡單看了下前面的匯編,主要內容為,把v32 放到 v45中,大小為32字節

    10.繼續分析

    接下來看一下sub_180005c00 函數,使用了v27,之前分析出來的密文地址就在v27中,v30沒看出來,應該是傳出參數后面用到了。

    猜測這個函數對密文進行一波操作,看一下返回值用來做什么,這個偽代碼看的頭疼,匯編看一下。

    .text:0000000180004021                 call    sub_180005C00.text:0000000180004026                 mov     rbx, rax.text:0000000180004029                 mov     r14, [rax+8]    ;返回值+8的內容給 r14.text:000000018000402D                 sub     r14, [rax]       ; r14 - 返回值的內容.text:0000000180004030                 mov     rcx, r14        ; 得到一個大小 Size
    

    人工反編譯一下 首先確定rax為一個指針 *(rax+8) - *rax 就是這個地址里面存儲了兩個值,拿第二個值減第一個值得到一個size。

    此時猜測,這兩個值或許是 密文的開始地址與結束地址?

    然后用這個size 申請了一塊內存 , IDA 命名為 Block , sub_18000B060 之前分析過, 對*v12進行操作, 結果給到Block

    把V12代入rax中 , *(v12+8) - *v12 , 結束地址減去開始地址得到 size

    由此可以驗證猜測, *v12 為密文開始地址 ,V13為密文大小

    11.繼續分析第三個方框的內容

    以v13 + 1 的大小 申請了一塊內存 v14 , sub_18000B060 對 Block 再次進行操作, 結果給到v14。

    v14的最后一個字節置為0 ,推測已經把密文轉換為字符串了 , 需要一個 NULL 結尾。

    ;v15 = r8d   rcx = v13    rbx = v14 .text:0000000180004094                 movsxd  rcx, r14d.text:0000000180004097                 movzx   r8d, byte ptr [rcx+rbx-1]
    

    由上可得 v15 = v14[v13-1] , 也就是從v14中取了一個字節的值 ,位置在null字符的前一byte。

    12.繼續分析sub_180006AC0

    可以看到,sub_180006AC0 的參數 , v45(256字節數組),block ,v13。

    結合之前對 sub_180007000的分析,可以得知, 目前v45的狀態 ,v45[0-31]為32字節的類似密鑰的東西 v45[0xF0] 為 v10的神秘數據 ,v13為Block大小。

    跟進簡單查看 ,查看后感覺可讀性不好,筆者對照匯編代碼,重新修改了一下反編譯代碼。

    __int64 __fastcall sub_180006AC0(v45,block,block_size){   if ( block_size )  {    v3 = block;    v5 = v45 + 0xF0 - (_QWORD)block;           //v45+0xF0的地址  減去  block的地址得到v5    v6 = ((block_size - 1) >> 4) + 1;          //做為外圈循環的次數    do    {      v7 = *v3;                  //v7為 xmmword 16字節浮點寄存器 ,把block的內容取16字節給v7  16字節符合AES塊大小      //由此推測block是真正的密文,將在這個函數中進行解密操作       sub_180007320(v3, v45);    //用到了AES解密常量  應該是解密相關  并且對推測的key  也就是前32字節有一些操作      v8 = 16i64;                //內圈循環16次      do      {        result = *((char*)(v3 + v5));       //block地址 + v5偏移  取一個字節內容        *(char*)v3 ^= result;               //取block的1字節數據,與block地址 + v5偏移  進行異或        v3 = (__int128 *)((char *)v3 + 1);  //block += 1        --v8;                                //總共16次 也就是16個字節異或      }      while ( v8 );      v5 -= 16i64;                          //外圈循環  v5 每次-16  也就是每次異或 異或的值都會變化 范圍為-16字節      v45 + 0xF0 = v7;                        //block的16字節內容  給到v45+0xF0      --v6;                                    //外圈循環次數    }    while ( v6 );  }  return result;  }
    

    根據目前的分析,可以推測 ,sub_180006AC0函數為 主要的解密算法函數,看著像是 AES CBC模式,因為對算法不熟悉,大膽猜測一下。

    key存放在v45中, 前32字節 ,也就是256位 , iv存放在 block+v5中 (不清楚對不對)

    13.繼續分析剩下的內容

     

     

    好的好的,看著有點頭疼,后面的代碼大概意思就是,又對解密后的數據進行了一系列操作,最后返回了一個緩沖區。

    讀者感興趣可以自行分析,實在是寫不動了。

    釜底抽薪 :得到JS代碼

    1.根據前面的分析,我們已經大致了解了程序流程,來到調用解密函數的函數,只需要在徹底解密后,送到JS引擎執行的時候,拿到解密的JS代碼即可。

     

    2.根據上層調用代碼,可以得到,解密后返回了一個值,作為調用JS函數的參數 ,定位到678F偏移處,x64dbg同步定位。

    3.斷下后查看v28的內容 , RSP+20 的位置,然后繼續查看這個指針的指針的內容,最后得到了解密后unicode形式的JS代碼。

    4.把內容拷走,拿到010editor,把00去掉,變成ascii形式,檢查一下得到的數據。

    看起來跟密鑰有關的一串字符編碼數據:

    搜索一下license相關的數據, 找到不少,看起來也像是代碼,應該沒問題

    指鹿為馬 :破解可行性分析

    修改文件破解

    如果懂算法與NodeJS,可以通過分析,找到關鍵的key等數據,對app.asar進行解包解密操作得到JS代碼進行修改后,打包回去即可

    可能遇到的問題:對app.asar進行完整性校驗。

    內存破解

    簡單說幾種思路,由于main.node是后加載的模塊,所以內存破解有些難度。

    1. 調試器加載 :參照上述手段,在模塊加載通知中斷下,定位到解密函數下斷,修改內存中的JS代碼
    2. 導出表HOOK:參考病毒木馬使用的進程替換(傀儡進程)技術,創建進程后掛起,由于main.node中的node api是使用框架中的導出api,所以可以替換導出函數為自己的函數,在調用時進行參數判斷,如果為JS代碼,則修改
    3. DLL劫持:替換main.node,由自己加載真正的main.node并調用,調用時,定位到解密函數并hook,等待JS代碼并修改
    4. PE代碼注入 :修改框架的PE文件,并加載自己的DLL,加載后進行導出表hook

    可能遇到的問題:對main.node或者框架進行完整性校驗,更加強大的反調試手段。

    方法還有很多,不再一一列舉,這里只能提出思路

    點到為止 :總結

    1. 通過這次逆向分析,踩了不少坑,學到了不少東西,并且加深了逆向技術的基礎。
    2. 作為一個逆向練習生,遇到不懂的,不會的,應該迎難而上,揚長避短,不可輕言放棄。
    3. 遇到一個糾結的地方,不要過度停留,逆向分析應該是分析大方向,站在開發者角度,根據分析出來的功能猜測作者的意圖,以找到關鍵突破點。

    結語

    1. 由于筆者對算法與Node Js開發并不熟悉,所以沒辦法得到密鑰與其它解密數據(文章中關于算法的一些操作皆為推測,相信熟悉算法的大佬可以看出來密鑰所在)
    2. 對于最后得到的JS代碼也沒辦法判斷到底完不完整,是否還有未解密的部分,所以只能到此為止了(看起來是完整了)
    3. 經過筆者一段時間的努力,已經成功實現內存破解,詳情見下篇。
    函數調用js代碼
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    由此可以推測,之前找到的main.node,可能就是解密模塊。此時找到了AES的算法常量,前兩個是重復的,可能是插件問題。只能去問度娘了,搜索一下AES加密解密原理與 C 實現代碼
    近年來,瀏覽器安全事件頻發,給人們帶來嚴重的損失。目前這兩類技術的研究重點主要在于對瀏覽器的JavaScript引擎的模糊測試,基礎思想都是首先將JS代碼轉換為語法樹AST,再在語法樹上進行相關變異操作。同時對其他部分進行變異,以便可以發現類似的或新的錯誤。⑤DIE記錄運行時覆蓋反饋信息決定新文件將被保存。此外,DIE同樣記錄自定義函數的參數和返回值的類型,以便在新構建的AST節點中進行合法調用。
    最近遇到webpack類型的網站越來越多,所以在B站學習了一下,今天來實戰一波。
    企業安全規劃建設過程中,往往會涉及到開發的代碼安全,而更多可以實現落地的是源代碼安全審計中,使用自動化工具代替人工漏洞挖掘,并且可以交付給研發人員直接進行安全自查,同時也更符合SDL的原則,此外可以顯著提高審計工作的效率。
    高達40%的npm包依賴的代碼至少包含一個公開漏洞,因此如何解決 Node.js 應用的安全性檢測是一個十分重要的問題。
    VX小程序逆向分析
    2023-06-29 09:16:31
    Frida雖然確實調試起來相當方便,但是Xposed由于能夠安裝在用戶手機上實現持久化的hook,至今受到很多人的青睞,對于微信小程序的wx.request API。背景知識眾所周知,Xposed主要用于安卓Java層的Hook,而微信小程序則是由JS編寫的,顯然無法直接進行hook。對于Xposed則沒有這個問題,只需指定微信的包名就會自動hook上所有的子進程。答案是可以的,如下所示:Xposed hook wx.request java層代碼得到發送的數據實現如下所示:得到響應數據的Xposed代碼就不貼了,方法同上。
    BurpCrypto在Web滲透測試中有一個關鍵的測試項:密碼爆破。使用方法BurpCrypto安裝完成后會在BurpSuite中添加一個名為BurpCrypto的選項卡,打開選項卡可進入不同加密方式的具體設置界面。找的密文對應的明文BurpSuite中有一個飽受詬病的問題,在測試器的測試結果中,無法顯示原始Payload,也就是字典內容。因為Java內置的JavaScript不包含瀏覽器中的window、document、console等API,不過好在此類組件一般不會對加密的核心功能造成影響,但是還是需要將調用此類組件的相關代碼進行刪除或者調整。
    前陣子做了一下 Dice CTF 2021,做出了幾個 XSS ,本次就寫一下包括復現題在內的所有學習筆記。
    若讀者因此作出任何危害網絡安全行為后果自負,與本號及原作者無關。但是由于官網的版本不是最新的,APP會強制你升級。而升級后的APP,是進行加固后的,無法使用frida進行hook,注入進程。那同樣也無法使用SSL Unpinning進行限制客戶端校驗證書。首先使用burp進行抓包代理,官網版本的APP,是可以輕松抓到APP的包的。但是內容使用了加密,具體什么加密是不得而知。
    而iOS呢肯定是iPhone了,但是如何選系統如何自己越獄呢?比如手機越獄后,發現開不開機無法進入主界面,有可能是注入的插件有問題。然后進入frida-ios-dump腳本的目錄直接執行./dump 包名。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类