看雪.WiFi萬能鑰匙 CTF 2017第八題 點評及解題思路

Editor發表於2017-06-22


看雪CTF 2017 比賽進行至第八題

截止至今天中午12點,第八題破解人數為5人!

看雪.WiFi萬能鑰匙 CTF 2017第八題 點評及解題思路

攻擊方排名前十名波動不大,

loudy從第十位上升至第7位,

poyoten再次衝進前十位~

看雪.WiFi萬能鑰匙 CTF 2017第八題 點評及解題思路

前十名能否保守住自己的位置呢?

是否會有黑馬一戰成名呢?

期待ing......

接下來我們來回顧一下第八題

看看 看雪評委和出題者是怎麼說的ヾ(๑╹◡╹)ノ"。


看雪評委 netwind 點評

該題亮點依然在反除錯上,用虛擬機器進行程式碼保護,透過執行緒動態加解密主要程式碼,透過校驗和檢查程式碼完整性,根據時間來反除錯,另外還將實際程式碼替換為假程式碼,防止反彙編,在反除錯方面讓攻方選手舉步維艱。演算法上採用了RSA演算法的思想,解決掉反除錯後,參考RSA演算法可以求解。

作者簡介


作者loudy,原名吳林峰,畢業於北京航空航天大學電子資訊工程專業,當前從事工作出於保密規定暫不公開。愛好跑步、籃球、電影;熱衷程式設計、特別是逆向分析。2007年接觸看雪,以潛水學習為主,也希望多認識有相同愛好的朋友。


看雪 CTF2017 第八題設計思路


一、答案

UFdVXVRTVVFYWltdXV9XQkFDQEUtLVBTV1BWVVFQUVxeWVxfWENDQkRCQE5CTEBCWFZaVVRTVlxZU1lcXC0tVGhpNV9pc19BX1ZlcnlfU2ltcGxlX1Rlc3Qh

二、基本設計思想

(1)簡單虛擬機器(使用虛擬暫存器傳值)

實現了系統函式呼叫、CMP、JNZ、XOR等呼叫

(2)反除錯

主要使用了3種

1、  執行緒動態加密解密主要程式碼

2、  CheckSum檢查主要程式碼

3、  時間判斷

(3)反彙編

主要透過將實際程式碼替換為假程式碼,防止反彙編。

(4)演算法設計

主要是利用RSA思想,其中(比較小)

P:900F0CA3041C345B

Q:98FCAE63A170C363

N:56172073862A662A8D6BB1A135999031

E:D9C382944A461EE3

D:4A064A97921BDF9E3F354E9020AE054F

首先對輸入進行base64解碼,然後將解碼後註冊碼分成三段,

1、  第一段解碼得到E,再和固定值做大數乘法運算,結果和另一固定值比較,相等則到下一步

2、  第二段解碼得到N,再和固定值做大數乘法運算,結果和另一固定值比較,相等則到下一步

3、  透過E和N對第三段加密,和記憶體固定值比較,相等則成功

三、破解思路

1、先解決反除錯和反反彙編,將真正程式碼還原

2、識別大數乘法運算,透過固定值和大數除法還原E、N,得到第一段和第二段註冊碼。

3、透過E、N解出D

4、用N和D對固定值解密,得到第三段註冊碼。

5、組合三段註冊碼,base64加密,得到最終的註冊碼。


下面選取攻擊者 風間仁 的破解分析        

1. TlsCallback

建立了6個執行緒, 前3個執行緒是負責smc解碼的, 後3個執行緒沒用 

.text:00402D30 TlsCallback_2

執行緒1: 解碼004025DC處的跳轉及check1函式

.text:00402830 thread1
 
.text:004025DC                 push    offset loc_4025E2
.text:004025E1                 retn
.text:004025E2                 lea     ecx, [ebp+var_110]
.text:004025E8                 push    ecx
.text:004025E9                 call    check1

執行緒2: 解碼0040263C處的跳轉及check2函式

.text:00402970 thread2
 
.text:0040263C                 push    offset loc_402642
.text:00402641                 retn
.text:00402642                 lea     eax, [ebp+var_110]
.text:00402648                 push    eax
.text:00402649                 call    check2

執行緒3: 解碼0040269C處的跳轉及check3函式

.text:00402A90 thread3
 
.text:0040269C                 push    offset loc_4026A2
.text:004026A1                 retn
.text:004026A2                 lea     edx, [ebp+var_110]
.text:004026A8                 push    edx
.text:004026A9                 call    check3


2. 主流程

一個自定義的虛擬機器

看雪.WiFi萬能鑰匙 CTF 2017第八題 點評及解題思路


校驗函式

.text:00402700 fn_check


檢測程式碼改動


.text:00402481                 call    check_text_areas


sn=base64_decode(sn)

.text:0040251D                 call    base64_decode


sn的格式(共90位): (20位)--(39位)--(27位)

.text:00402573                 cmp     [ebp+var_130], 90
.text:0040257A                 jnz     short loc_4025AC
.text:0040257C                 movsx   edx, [ebp+Dst+14h]
.text:00402583                 cmp     edx, '-'
.text:00402586                 jnz     short loc_4025AC
.text:00402588                 movsx   eax, [ebp+Dst+15h]
.text:0040258F                 cmp     eax, '-'
.text:00402592                 jnz     short loc_4025AC
.text:00402594                 movsx   ecx, [ebp+Dst+3Dh]
.text:0040259B                 cmp     ecx, '-'
.text:0040259E                 jnz     short loc_4025AC
.text:004025A0                 movsx   edx, [ebp+Dst+3Eh]
.text:004025A7                 cmp     edx, '-'
.text:004025AA                 jz      short loc_4025B2


校驗前20位

(sn1 xor abcdefg...) * 98765432109876543210123 == 1549780652036258484424751705102781884386113

.text:004025E9                 call    check1

校驗中間39位

(sn2 xor abcdefg...) ^ 2 == 13095069099216326605010245808779535277211541324456558063162414338128147458401

.text:00402649                 call    check2

檢驗後27位, sn3視為16進位制

sn3 ^ 15691529100101820131 mod 114433688655117320765854989491151409201 == 71639176673360967005214790689576394595

.text:004026A9                 call    check3

sn3作為16進位制轉換的時候是有符號轉換的, 所以導致>=80的值無法正常轉換

這裡只需要關心能產生0x00的值即可(有挺多個, 如0x89) 

for (int i = 8; i < 16; i++)
{
    for (int k = 0; k < 16; k++)
    {
        int v = (char)((i << 4) | k);
        char v1 = v / 16;
        char v2 = v % 16;
        v1 += v1 < 0 ? 0x37 : 0x30;
        v2 += v2 < 0 ? 0x37 : 0x30;
        // 這裡非數字字母的字元, 後面都會被0替代
        printf("%02X: %c%c\n", (BYTE)v, v1, v2);
    }
}


3. 後27位計算


已知:

e = 15691529100101820131

n = 114433688655117320765854989491151409201

m = 71639176673360967005214790689576394595


分解得到

d = 98395538376216701876091105738065053007


c = m ^ d mod n = 55986991232018409201158808992848352475 (2A1EB3C9579DFA307CF5B6C8730114DB) 


c中>=0x80的是無法透過轉換得到的(如B3, C9, ...)


sn3(27位元組) > c (16位元組)

c ^ e mod n = m, 根據(a * b) mod n = (a mod n) * (b mod n) mod n

得 (c mod n) * (c mod n) * ... mod n = m

再由c mod n = (c + k * n) mod n, 代入上式得到

(c + k * n) ^ e mod n = m


根據下面這兩個條件可以立刻得到很多解(如: 0208674855670d0560353c3a1d3e242e217766)

sn3 = c + k * n

sn3中的位元組必須小於0x80


得到的解, 在前面填充可以轉換成00的值:  89898989898989890208674855670d0560353c3a1d3e242e217766

與前面的串連線起來base64得到最終結果 

UFdVXVRTVVFYWltdXV9XQkFDQEUtLVBTV1BWVVFQUVxeWVxfWENDQkRCQE5CTEBCWFZaVVRTVlxZU1lcXC0tiYmJiYmJiYkCCGdIVWcNBWA1PDodPiQuIXdm


4. 窮舉指令碼

import itertools
n=114433688655117320765854989491151409201
e=15691529100101820131
c=55986991232018409201158808992848352475
def valid_result(v):
    sv=hex(v)[2:]
    sv_len=len(sv)
    if (sv_len&1) != 0:
        sv='0'+sv
        sv_len=sv_len+1
    for i in itertools.count(0,2):
        if (i>=sv_len):
            break
        if (ord(sv[i])>=0x38):
            return False
    return True
def solve(ibegin,iend):
    g=0
    nc=c
    k=0
    for i in itertools.count(0):
        g=g+1
        nc=nc+n
        if ((ibegin+i)>=iend):
            break;
        #print(nc)
        #print(pow(nc,e,n))
        if (g>=1000000):
            print(ibegin+i)
            g=0        
        if (valid_result(nc)):
            print('---')
            print(i)
            print(nc)
            print(hex(nc))
            #break
    return
solve(0,4294967296)
'''
---
396154
45333533916159234226406484520676079360374630
0x208674855670d0560353c3a1d3e242e217766
---
456935
52288927946305920099875916636937753163020611
0x2583f59392b7266031a47246a1e672b013943
..


最後感謝 WiFi 萬能鑰匙安全應急響應中心的贊助支援, 接下來的比賽大家一定要使出洪荒之力哦!↖(^ω^)↗ 比心 ❤ 


 贊助商 


上海連尚網路科技有限公司成立於 2013 年,是一家專注於提供免費上網和內容服務的移動網際網路企業。連尚網路自主研發的核心產品 WiFi 萬能鑰匙,以分享經濟的模式,透過雲端計算和大資料技術,利用熱點主人分享的閒置WiFi資源,為使用者提供免費、穩定、安全的上網服務,以幫助更多的人上網,找到屬於他們的機會,改變自己的命運。                    

相關文章