看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析

Editor發表於2021-12-16

解析影片地址:https://www.bilibili.com/video/BV16i4y1d7g6/


此題沒有反除錯,只有一定的混淆。

對於初級參賽者,需要對抗本題的混淆。

對於中級參賽者,需要熟悉平方剩餘演算法。

對於高階參賽者,需要發現並修復CrackMe中的bug。


出題團隊在賽前釋出了一部情感短影片,並將解題思路隱藏於其中。賽後又釋出了一部解析影片,深入講解了破解方法。


作為第一個配短影片的CTF賽題,此題出題思路別緻,影片製作專業,是一個有里程碑意義的CTF賽題!


截至比賽結束,此題共計圍觀人數:1957人,攻破戰隊數:4。


分別是:金左手、中婭之戒、mininep、辣雞戰隊。從圍觀人數來看,此題吸引了不少參賽成員。特意為CTF賽題製作高水準的配套微電影還是頭一次見吧!這不,解析版的影片也為大家奉上啦~


看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析


《生命的饋贈》出題影片:https://www.bilibili.com/video/bv1Uh411s7u4

看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析


出題團隊簡介


第十題《生命的饋贈》出題方:【GRAFFINDOR】戰隊。


看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析


【GRAFFINDOR】戰隊成員如下:


看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析


賽題設計思路


題目設計說明:防守有兩部分,程式程式碼混淆和數學保護。


一、混淆

1、程式碼亂序處理

行與行之間加入jmp,透過jmp銜接每一行程式碼。


定義:定義了一個結構體管理每行程式碼,結構體如下。

struct CodeLineToExpand{OrderType m_Type;//原來程式碼的型別Param1;Param2;OldAddr;  //原來程式碼的地址OldAddrToJmpOrCall;//原來程式碼中要跳轉的目標地址OldIndexValue;NewSize;//已經加入了遠相對jmp後的大小NewAddr;NewAddrToJmpOrCall;RamdomValue;//隨機值NewCode;//新的程式碼}CTE[nCodeLines];int MapNewToOld[nCodeLines];//儲存新的Line和舊的Line之間的對應關係int CodeLineOldAddrBegin;//原來程式碼地址的開始int CodeLineOldAddrEnd;//原來程式碼地址的結束(不包含本地址)


步驟:

(1)將某一行程式碼nCodeLines的原始資訊填入CTE陣列。
計算出nCodeLines,填好CTE陣列的每個元素的m_Type、Param1、Param2、OldAddr、OldAddrToJmpOrCall、OldIndexValue。


(2)對CTE每個元素賦予隨機值,以該隨即值的從小到大順序重新組合程式碼。
計算出隨機值填入RamdomValue,然後以此排序,排序後的結果放入MapNewToOld陣列。


MapNewToOld陣列按照索引順序(NewIndex)來放置OldValue的值,順序為從小到大。


(3)某行程式碼新地址的計算方法(CTE: NewAddr)
遍歷MapNewToOld陣列,除去第0個,每個元素對應的CodeLineToExpand結構體的NewAddr都為前面的元素CodeLineToExpand結構體的NewAddr+NewSize


(4) 新CodeLine中的遠相對跳轉中相對地址的計算方法
遍歷CTE陣列,找它下一個元素的NewAddr配合自己的NewAddr進行計算。


(5)新的jmp\call目標地址的計算方法(假設原始碼僅為程式碼,不做它用,且程式碼為Jmp或者Call)


相對跳轉的修正:若原來程式碼要跳轉的地址not in [CodeLineOldAddrBegin,
CodeLineOldAddrEnd]
中,則用NewAddr和OldAddrToJmpOrCall進行修正;反之,尋找原來程式碼跳轉地址對應的CodeLineToExpand,用NewAddr和原來程式碼跳轉地址對應的CodeLineToExpand中的NewAddr進行修正。


絕對跳轉的修正:若原來程式碼要跳轉的地址not in [CodeLineOldAddrBegin,
CodeLineOldAddrEnd]
中,則不需要修正;反之,尋找原來程式碼跳轉地址對應的CodeLineToExpand,原來程式碼跳轉地址對應的CodeLineToExpand中的NewAddr進行修正。


2、初步替換jmp指令


按長度分為9種。

// 第一種  長度:6push Addrret// 第二種  長度:0x1Cpush eaxmov eax,Addrpush eaxmov [esp-4],eaxmov eax,[esp+4]mov [esp],eaxmov eax,[esp-4]mov [esp+4],eaxpop eaxret// 第三種1 長度:0xCmov dword ptr[esp-4],Addrjmp[esp - 4]         // 第三種2 長度:Cmov dword ptr[esp-4],Addrsub esp,4ret// 第四種  長度:0x2Dpush eaxmov dword ptr[esp-4],Addrmov eax,[esp-4]mov [esp-8],eaxsub esp,4mov eax,[esp+4]mov [esp],eaxmov eax,[esp-4]mov [esp+4],eaxmov eax,[esp]add esp,8   //add esp,4jmp [esp-4] //ret// 第五種  長度:0x34push Addrpush eaxmov eax,Addrmov eax,[esp]//push eaxmov eax,Addrpush eaxmov [esp-4],eaxmov eax,[esp+4]mov [esp],eaxmov eax,[esp-4]mov [esp+4],eaxpop eax//add esp,4pop eaxadd esp,4jmp [esp-4]// 第六種(4+5) 長度:0x86push Addrpush eaxmov eax,Addrpush eaxmov dword ptr [esp-4],Addrmov eax,[esp-4]mov [esp-8],eaxsub esp,4mov eax,[esp+4]mov [esp],eaxmov eax,[esp-4]mov [esp+4],eaxmov eax,[esp]add esp,8   //add esp,4mov eax,[esp]push eaxmov eax,Addrpush eaxmov [esp-4],eaxmov eax,[esp+4]push eaxmov dword ptr[esp-4],Addrmov eax,[esp-4]mov [esp-8],eaxsub esp,4mov eax,[esp+4]mov [esp],eaxmov eax,[esp-4]mov [esp+4],eaxmov eax,[esp]add esp,8   //add esp,4mov [esp],eaxmov eax,[esp-4]mov [esp+4],eaxpop eaxadd esp,4pop eaxadd esp,4jmp [esp-4]// 第7種  長度:0x59push Addrpush 0x7FFA08ACjmp [esp]nopnopnopnopnopnopnopnopnopnopnopnopnoppush ebpmov ebp,espadd esp,-34push ebxpush ecxpush eaxpush esipush edilea edi,[ebp-34h]mov ecx,Dmov eax,0x0CCCCCCCCrep stos dword ptr [edi]mov [ebp-4],ecxmov eax,[ebp+8]mov edx,dword ptr [esp+4]mov ecx,dword ptr [esp+8]mov dword ptr [ebp-30h],1mov edx,dword ptr [ebp-30h]mov dword ptr [ebp-34h],edxmov ecx,[ebp-4h]pop edipop esipop eaxpop ecxpop ebxleaveret// 第8種  長度:0x42pushfdpush eaxmov eax, 4mul eaxlea eax, [4 * eax]mov[esp - 4], eaxmov eax, 4shl eax, 4sub eax, 4sub[esp - 4], eaxmov eax, [esp - 4]sub eax, 4mov[esp - 4], eaxpop eaxjne $ + 0x13call $+5add dword ptr [esp],0x13mov eax,[esp+4]mov [esp-4],eaxpopfdadd esp,4mov dword ptr[esp - 4], Addrsub esp, 4ret// 第9種(7+8) 長度:0x99// 第10種 長度:0x46pushfdpush eaxxor eax,Addrxor eax,64test eax,eax//push eaxmov eax,Addrpush eaxmov [esp-4],eaxmov eax,[esp+4]mov [esp],eaxmov eax,[esp-4]mov [esp+4],eaxpop eaxadd esp,4//xor eax,64xor eax,[esp]push eaxadd esp,8popfdsub esp,8pop eaxpop [esp-4]jmp [esp-C]7FFBDD3B pushfd + retn7FFAF6DF popfd + retnaddreaxfd


3、透過計算得出jmp的目標地址


有8種計算方式,以長度區分。

// 第1種 長度:0x2dpushfd\npush eax\npush $1\nadd dword ptr[esp], $2\nshl dword ptr[esp], $3\nxor dword ptr[esp], $4\nadd dword ptr[esp], $5\nxchg eax,[esp]\nxchg eax,[esp+8]\nxchg eax,[esp]\npopfd\npop eax\nret // 第2種 長度:0x31push eax\nmov eax, $1\nlea eax, [eax + $2]\npush eax\nmov[esp - 4], eax\nmov eax, [esp + 4]\nmov[esp], eax\nmov eax, dword ptr[esp - 4]\npushfd\nshl eax, $3\nadd eax, $4\nxor eax, $5\npopfd\nmov[esp + 4], eax\npop eax\nret// 第3種 長度:0x2fpushfd\npushfd\nadd esp,8\nmov dword ptr[esp - 4], $1\nshl dword ptr[esp - 4], $2\nadd dword ptr[esp - 4], $3\nxor dword ptr[esp - 4], $4\nadd dword ptr[esp - 4], $5\nsub esp, 8\npopfd\nret// 第4種 長度:0x65pushfd\npush eax\nmov dword ptr[esp - 4], $1\nmov eax, [esp - 4]\nmov[esp - 8], eax\nsub esp, 4\nshl dword ptr[esp - 4], $2\nmov eax, [esp + 4]\nadd dword ptr[esp - 4], $3\nmov dword ptr[esp], eax\nmov eax, [esp - 4]\nmov[esp + 4], eax\nmov eax, [esp]\nmov [esp-8],eax\nadd dword ptr[esp + 4], $4\nxor dword ptr[esp + 4], $5\nmov eax,[esp+4]\nmov [esp-8],eax\nlea esp, [esp + 8]\npopfd\nlea esp,[esp-4]\nmov eax,[esp-4]\nmov [esp],eax\nmov eax,[esp-8]\nret// 第5種 長度:0x5dpushfd\npush $1\npush eax\nmov eax, $2\nmov eax, [esp]\nshl dword ptr[esp + 4], $2\npush eax\nmov eax, 1\npush eax\nmov[esp - 4], eax\nmov eax, [esp + 4]\nmov[esp], eax\nmov eax, [esp - 4]\nmov[esp + 4], eax\npop eax\nxor dword ptr[esp + 8], $3\nadd esp, 4\nmov eax, $4\nadd eax, $5\nadd dword ptr[esp + 4], eax\npop eax\nadd esp,4\npopfd\nlea esp,[esp-4]\nmov eax,[esp-4]\nmov [esp],eax\nmov eax,[esp-8]\nret// 第6種 長度:0x82push $1\npush eax\nmov eax, edi\npush eax\npushfd\npushfd\npushfd\nadd esp, 0ch\nmov dword ptr[esp - 4], $3\nmov eax, [esp - 4]\nmov[esp - 8], eax\nsub esp, 4\nmov eax, [esp + 4]\nmov[esp], eax\nmov eax, [esp - 4]\nmov[esp + 4], eax\nmov eax, [esp]\nadd esp, 8\nmov eax, [esp]\nxor eax, [esp]\nmov eax, [esp + 4]\nadd eax, $2\nxor eax, $3\nmov[esp + 4], eax\npush eax\nmov eax, $4\npush eax\nmov[esp - 4], eax\nmov eax, [esp + 4]\nmov[esp], eax\nmov eax, [esp - 4]\nmov[esp + 4], eax\npop eax\nadd esp, 4\npop eax\nshl dword ptr[esp], $4\nadd dword ptr[esp], $5\nsub esp,14h\npopfd\nlea esp,[esp + 10h]\nret// 第7種 長度:0x98push $1\npush eax\nmov eax, $4\npush eax\nmov[esp - 4], eax\nmov eax, [esp + 4]\nmov[esp], eax\nmov eax, [esp - 4]\nmov[esp + 4], eax\npop eax\nlea esp, [esp + 4]\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\npush ebp\nmov ebp, esp\nlea esp, [esp - 34h]\npushfd\npush ebx\npush ecx\npush eax\npush esi\npush edi\npush edx\nlea edi, [ebp - 34h]\nmov ecx, 0xD\nmov eax, 0x0CCCCCCCC\nrep stos dword ptr[edi]\nmov[ebp - 4], ecx\nmov eax, [ebp + 8]\nmov eax, ebp\nmov edx, dword ptr[esp + 4]\nmov ecx, [eax + 4]\nadd ecx, $2\nxchg ecx, edx\nmov ecx, dword ptr[esp + 8]\nmov dword ptr[ebp - 30h], 1\nadd edx, $3\nshl edx, $4\nmov ecx, edx\nmov edx, dword ptr[ebp - 30h]\nxor ecx, $5\nlea ebx, [eax + 4]\nmov dword ptr[ebp - 34h], edx\nmov [ebx], ecx\nmov ecx, [ebp - 4h]\npop edx\npop edi\npop esi\npop eax\npop ecx\npop ebx\npopfd\nleave\nret// 第8種 長度:0xafpushfd\npush $1\npush eax\npush edx\nmov eax, 4\nmul eax\nlea eax, [4 * eax]\nmov[esp - 4], eax\nmov eax, 4\nshl eax, 4\nsub eax, 4\nsub[esp - 4], eax\nmov eax, [esp - 4]\nsub eax, 4\nmov[esp - 4], eax\npop edx\npop eax\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\npush ebp\nmov ebp, esp\nadd esp, -34h\npush edx\npush ebx\npush ecx\npush eax\npush esi\npush edi\nlea edi, [ebp - 34h]\nmov ecx, 0xD\nmov eax, 0xCCCCCCCC\nrep stos dword ptr[edi]\nmov[ebp - 4], ecx\nmov eax, [ebp + 8]\nmov edx, dword ptr[esp + 4]\nmov ecx, dword ptr[ebp + 4]\ntest edx, 3\nlea ebx, [ebp + 8]\nmov dword ptr[ebp - 30h], 1\nmov edx, ecx\nxor edx, $2\nshl edx, $3\nmov eax, edx\nmov edx, dword ptr[ebp - 30h]\nmov dword ptr[ebp - 34h], edx\ncmp dword ptr[ebp - 34h], 0\nadd eax, $4\nadd eax, $5\n


4、替換後的程式碼進行拆分成塊 

拆分的方法和步驟0一致,相當於做二次處理。


5、為了降低拆分後程式碼的規律性,引入了無效的程式碼片段 


四種片段,隨機填充。

1、長度 58push ebpmov ebp, esplea esp, [esp - 34h]push ecxpush edxpush ebxpush esipush edipushfdmov edi, fs: [30h]lea edi, [edi + 8h]mov edi, [edi]lea ebx, [ebp]mov ecx, edixchg edx, [ebp]add ecx, 3chmov ecx,[ecx]add edi, ecxcall $ + 5pop ecxlea edi,[edi + 74h]lea ecx,[ecx + 29h]sub ebp, 4mov[ebp], edxlea ebx,[ebp]mov[ebx + 4], ecxcmp edi, 12hje $ - 55hpopfdpop edipop esipop ebxpop edxpop ecxleaveretnopnopnopnopnopnopnop        2、長度 21push ebpmov ebp,espsub esp,-34hpushadmov edi,fs:[30h]lea edi,[edi+8h]mov edi,[edi]mov eax,edilea eax,[4*eax]push eaxpop edipopadleave3、長度 21mov edi,edipush ebpmov ebp,esplea esp,[esp-22h]mov dword ptr [ebp-4h],ecxmov dword ptr [ebp-8h],ecxmov dword ptr [ebp-ch],ecxmov dword ptr [ebp-1ch],ecxmov esp,ebppop ebpjmp $+8nopnopnop4、長度 42call $ +0x2Emov eax, eaxcall $ +0xBmov eax, eaxlea esp, [esp + 12]lea esp, [esp + 10h]mov eax, eaxmov eax, eaxcall $ +0x24mov eax, eaxmov eax, eaxcall $ +0x14mov eax, eaxlea esp, [esp - 4]call $ -0xDmov eax, eaxmov eax, eaxcall $ -0x30mov eax, eaxlea esp, [esp + 8h]5、長度 42call $ +0x2Emov eax, eaxcall $ +0x37mov eax, eaxlea esp, [esp + 12]lea esp, [esp + 10h]mov eax, eaxmov eax, eaxcall $ +0x24mov eax, eaxmov eax, eaxcall $ +0x14mov eax, eaxlea esp, [esp - 4]call $ -0xDmov eax, eaxmov eax, eaxcall $ -0x30mov eax, eaxlea esp, [esp + 8h]


二、數學保護


數學公式(逆運算):((format(Serial) ^2 mod P) * A + B) mod P) ^2 mod P = MD5(name)


引數:

看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析

驗證:
(((S^2 Mod P) * A + B) Mod P) ^2 Mod P = N 滿足該式子則成功。

破解思路:

1、把無效的程式碼片段替換為空,去除垃圾程式碼,保留有效程式碼。
2、去除拆分後成塊的程式碼中的jmp,將程式碼塊整合成有序程式碼。
3、透過trace找出最終跳轉地址的計算模板,然後透過文字處理計算出地址進行替換。
4、處理亂序:透過trace跟蹤出執行亂序的程式碼,截獲原始地址進行處理。


賽題解析


一、分析篇

程式碼被混淆了。


混淆規律:6個call之後,類似下面這樣平衡堆疊的指令下面一條,就是真實指令。

lea     esp, dword ptr ss:[esp+0x14]lea     esp, dword ptr ss:[esp+0x8]


二、逆向篇


輸入預設的 name/serial,記憶體訪問斷點,返回到這裡。

0043D6E1    51              push    ecx0043D6E2    E8 82FAFDFF     call    0041D169 ; 獲取serial0043D6E7    68 80B57D1F     push    0x1F7DB580 ; 這裡能看到name/serial0043D6EC    89DB            mov     ebx, ebx0043D6EE    50              push    eax0043D6EF    89E4            mov     esp, esp0043D6F1    B8 1D000000     mov     eax, 0x1D0043D6F6    90              nop


然後serial比較長度,必須是32位元組:


00466750    5D              pop     ebp00466751    83F8 20         cmp     eax, 0x20                                       ; 比較長度00466754    9C              pushfd


單步到這:

004DD1DE   C785 00FFFFFF 7>mov   dword ptr ss:[ebp-0x100], 0x10325476 ;md5初始化


看看記憶體中:

0019FD38  01 23 45 67 89 AB CD EF FE DC BA 98 76 54 32 10  #Eg壂惋簶vT2


猜測是md5演算法,但此時記憶體中已經出現了正確的md5值:

0019FDC4  F4 D5 16 EF CE 55 11 93 B6 6E E1 68 26 51 5A 4F  粽鏤U摱n醜&QZO


這正好是name(1A5FBFD826E1D12E)的md5值,所以,這裡應該是serial逆推回去算出來的,改一個位元組會發現驗證錯誤。


重新分析,發現這個call是關鍵:

004C4F17    E8 8840F7FF     call    00438FA4  ; 驗證call,ecx = name, edx = serial004C4F1C    68 66757D1C     push    0x1C7D7566 ; 這裡驗證完畢, al = 1 成功, al = 0 失敗004C4F21    50              push    eax
0049BFAE    B8 F8414000     mov     eax, 004041F8                              ; ASCII "驗證正確\n"0049BFB3    9C              pushfd0049BFB4    89E4            mov     esp, esp0049BFB6    9C              pushfd0049BFB7    89DB            mov     ebx, ebx
004CA73A    8D6424 08       lea     esp, dword ptr ss:[esp+0x8]004CA73E  ^ 0F85 BE38FAFF   jnz     0046E002                                   ; 爆破點,jmp,驗證成功004CA744    68 BAEB7025     push    0x2570EBBA
call 438fa4004318D5    81EC 28010000   sub     esp, 0x128


這裡提升堆疊空間,可以直接清0堆疊,看看堆疊會出現哪些變數。

0043E967                      8D6424 14                               lea     esp, dword ptr ss:[esp+0x14]0043E96B                      E8 A3B90900                             call    004DA313 ; 似乎是 string to bignum0043E970                      9C                                      pushfd


004C0B29                      89C0                                    mov     eax, eax004C0B2B                      8D6424 14                               lea     esp, dword ptr ss:[esp+0x14]004C0B2F                      E8 D059F9FF                             call    Mul ; 這裡似乎是 pow2 004C0B34                      9C                                      pushfd


456504這個函式,傳入2個引數(eax, ecx) ,傳出1個引數([esp+4])。


執行完看輸出地址,這個正好是:

EEA43B9D52515B49838AFAA50490DA0B * EEA43B9D52515B49838AFAA50490DA0B = DE75C834F482A299391D073F5D424CAB9AA9FE2AAE920EE2228766F45E16BC790019FDA4  79 BC 16 5E F4 66 87 22 E2 0E 92 AE 2A FE A9 9A  y?^鬴??挳*?0019FDB4  AB 4C 42 5D 3F 07 1D 39 99 A2 82 F4 34 C8 75 DE  獿B]?9櫌傯4萿?


所以上面是Mul,在Mul上面下斷點。


然後經過一個函式:

00444D59                      67:E8 21020100                   call    <modN>00444D5F                      50                               push    eax                                                          ; 返回1


返回結果為:

0019FDA4  C3 E1 2D 54 FD 5A A8 FC 4F DC D5 D1 6D D8 04 93  冕-T齔O苷裮??0019FDB4  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

看上去像是取模。


我們用:

DE75C834F482A299391D073F5D424CAB9AA9FE2AAE920EE2228766F45E16BC79 - 9304D86DD1D5DC4FFCA85AFD542DE1C3 = DE75C834F482A299391D073F5D424CAB07A525BCDCBC329225DF0BF709E8DAB


然後用yafu分解一下:

factor(0xDE75C834F482A299391D073F5D424CAB07A525BCDCBC329225DF0BF709E8DAB6)


fac: factoring 100621555269000733341031010157969998386759504095520400047147427430100793612982fac: using pretesting plan: normalfac: no tune info: using qs/gnfs crossover of 95 digits


starting SIQS on c72: 146405049556078485019294860272741026808150808686274920697977580425648851


==== sieving in progress (1 thread):   16656 relations needed ========           Press ctrl-c to abort and save state           ====


SIQS elapsed time = 0.6650 seconds.Total factoring time = 0.6730 seconds


factors found


P39 = 340282366920938463463374607424628147107P33 = 430245771712568276625619760299793ans = 1


其中P33太小,P39 = FFFFFFFFFFFFFFFFFFFFFFFE566B43A3。


驗證一下:

DE75C834F482A299391D073F5D424CAB9AA9FE2AAE920EE2228766F45E16BC79 Mod FFFFFFFFFFFFFFFFFFFFFFFE566B43A3 = 9304D86DD1D5DC4FFCA85AFD542DE1C3


所以上面那個函式是 Mod 0xFFFFFFFFFFFFFFFFFFFFFFFE566B43A3。


設N=FFFFFFFFFFFFFFFFFFFFFFFE566B43A3,在ModN位置下斷點,然後F9跑,然後發現Mul斷下來了。

6805A57D5B006445AC1B0675EB188435 *  9304D86DD1D5DC4FFCA85AFD542DE1C3  = 3BBD360EF483631109E77CAB8B604BE7252D7537F13655FA919F38844130495F


斷下了後,發現記憶體中值發生了變化:

3BBD360EF483631109E77CAB8B604BE768906BBC53C8BB20F644044205801BE2


跟上面乘的結果比較,發現是大了一點點:

3BBD360EF483631109E77CAB8B604BE768906BBC53C8BB20F644044205801BE2 - 3BBD360EF483631109E77CAB8B604BE7252D7537F13655FA919F38844130495F = 4362F6846292652664A4CBBDC44FD283


再跑,發現ModN斷下來了:

00473134                      E8 471EFEFF                      call    <modN>00473139                      50                               push    eax


結果:24938628338F43651192F4F03FD24328


再跑,Mul斷下來了:

24938628338F43651192F4F03FD24328 * 24938628338F43651192F4F03FD24328 = 0539D2BEA6F99DC5F4B8C6AAD5DCBB1F9927D007969D817073CB54BFEF3DF6400019FD10  40 F6 3D EF BF 54 CB 73 70 81 9D 96 07 D0 27 99  @?錕T藄p仢???0019FD20  1F BB DC D5 AA C6 B8 F4 C5 9D F9 A6 BE D2 39 05  卉摘聘襞濝?


再跑,ModN斷下來,正好是0x4F5A512668E16EB6931155CEEF16D5F4


記憶體中結構,恰好等於 md5(name)的值:

0019FD10  F4 D5 16 EF CE 55 11 93 B6 6E E1 68 26 51 5A 4F  粽鏤U摱n醜&QZO


3、演算法篇

整理一下演算法:

設N = FFFFFFFFFFFFFFFFFFFFFFFE566B43A3

A = 6805A57D5B006445AC1B0675EB188435

B = 4362F6846292652664A4CBBDC44FD283


M = MD5(name) , 注意,記憶體中是little eddian的

S = hex(serial)


整個驗證演算法,可以用表示式來表示:

M = (((S ^ 2) Mod N) * A + B) ^ 2 Mod N


看數學表示式,實際上是 兩次平方模,然後比較name的md5。逆運算就是求平方剩餘。


平方剩餘公式是:

當 Y = X^2 Mod N ,且 N mod 4 = 3的時候

X1 = Y ^ ((N+1)/4) Mod N


平方剩餘有多解:另一解是 X2 = N - X1


所以這題其實有4解。


name: 1A5FBFD826E1D12E


serial: 

EEA43B9D52515B49838AFAA50490DA0B

115BC462ADAEA4B67C75055951DA6998

41B8103BEC6C05BC8D4E37DD2DF5D1E8

BE47EFC41393FA4372B1C821287571BB


經測試,這4解都可以透過驗證。


4、音樂篇


但是,當我們使用KCTF的時候:


MD5('KCTF') = 0xA0D99FB4D5ABF597979F99A2C6B11A7A ( 記憶體中位元組碼:7A 1A B1 C6 A2 99 9F 97 97 F5 AB D5 B4 9F D9 A0 )


求出來的4解是:

2EA6060B597BA4D12D2FC0A1DF7A5FB5

D159F9F4A6845B2ED2D03F5C76F0E3EE

48538B7EADCDD321FB83E1F4D227BAD9

B7AC748152322CDE047C1E09844388CA


遺憾的是,一個都無法透過!


看了一遍又一遍《生命的饋贈》,“所有曲目我都試過了,這密碼還是打不開”


為什麼會不對呢?各種百度,谷歌,原來,平方剩餘是有條件的。


Y = X^2 Mod N,X有解的條件是 Y^ ((N-1)/2) == 1 Mod N


第一次的時候,是有平方剩餘的,所以能解出兩解。

Z1 = 0000000000000000B0D3C2D4E7B7A3BA

Z2 = 6E000A013A6DF57F8ABD86D0120C88AD


但是第二次的時候,兩組資料都沒有平方剩餘!


這就有意思了,到底哪裡出問題了呢?再看一遍影片,發現缺了個琴音是破解的關鍵!


有沒有可能,Mod的時候,沒有模盡,使得結果多了一個N,然後取了低128bit,正好就有平方剩餘了呢?


於是,把Z1,Z2,分別 

Z1 + 2^128 - N = B0D3C2D6914C6017


求兩組平方剩餘:

05A6CC68CF60E9606195E9912BBF332A

FA593397309F169F9E6A166D2AAC1079


Z2 + 2^128 - N = 6E000A013A6DF57F8ABD86D1BBA1450A


求兩組平方剩餘:

6E66D51BBB5DFD0200F5BF564A7F1052

91992AE444A202FDFF0A40A80BEC3351


驗證發現,FA593397309F169F9E6A166D2AAC1079 是唯一透過的解!


注意:【最受歡迎戰隊獎】&【新思路獎】正在火熱評選中!歡迎大家投上寶貴的一票~


待評選(一):【最受歡迎戰隊獎】


看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析


長按二維碼立即投票!【最受歡迎戰隊獎】


【最受歡迎戰隊獎】


評選物件:

2021 KCTF秋季賽 參賽戰隊(包含防守方所有戰隊+攻擊方前20名戰隊)


評選方式:

登陸看雪賬號,在本帖為喜歡的戰隊投票,每個賬號可投1票。


投票時間:

12月15日 14:00 ~12月22日 14:00


獎品:

【最受歡迎戰隊獎】得票第一名:可獲得「HUAWEI WATCH GT2 華為手錶」

看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析


待評選(二):【新思路獎】

看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析

長按二維碼立即投票!


【新思路獎】


評選物件:

2021 KCTF秋季賽 參賽防守方戰隊


評選方式:

1、會員投票(佔比50%):在KCTF答題頁面投票,只有提交答案的選手才可投票。【快使用你們的特權~】

2、看雪KCTF專家評審團投票(佔比50%):評審團成員投票,每人一票。

投票時間:

比賽開始,直到比賽結束後一週。(12月22日12:00關閉投票通道)


獎品:

【新思路獎】得票第一名:可獲得「HUAWEI WATCH GT2 華為手錶」

看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析



看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析


往期解析


1、看雪·眾安 2021 KCTF 秋季賽 | 第二題設計思路及解析


2、看雪·眾安 2021 KCTF 秋季賽 | 第三題設計思路及解析


3、看雪·眾安 2021 KCTF 秋季賽 | 第四題設計思路及解析


4、看雪·眾安 2021 KCTF 秋季賽 | 第五題設計思路及解析


5、看雪·眾安 2021 KCTF 秋季賽 | 第六題設計思路及解析


6、看雪·眾安 2021 KCTF 秋季賽 | 第七題設計思路及解析


7、看雪·眾安 2021 KCTF 秋季賽 | 第八題設計思路及解析


8、看雪·眾安 2021 KCTF 秋季賽 | 第九題設計思路及解析


9、看雪·眾安 2021 KCTF 秋季賽 | 第十一題設計思路及解析



- End -



看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析

公眾號ID:ikanxue

官方微博:看雪安全

商務合作:wsc@kanxue.com

相關文章