Have a tea -(极客大挑战(SMC,fork
無殼,IDA打開64?
分析start函數(shù)。 smc?解密,通常處理smc?解密有兩種?法,如果是?較簡(jiǎn)單的?解密, 我們可以直接使?idapython寫?個(gè)腳本即可解決,如果碰?運(yùn)算不太好實(shí)現(xiàn)的smc?解密,?如這?。
嘗試動(dòng)態(tài)調(diào)試,我們要在下?的jmp指令處下斷點(diǎn)?
jmp跳轉(zhuǎn)?
?右鍵analyzed 選Force 把紅色代碼部分P鍵定義成函數(shù)
?F5起始地址,查看到main函數(shù),猜測(cè)后面為init函數(shù)
優(yōu)先查看init函數(shù)(先于main函數(shù)執(zhí)行
部分main函數(shù):
?發(fā)現(xiàn)調(diào)?了fork 來創(chuàng)建?進(jìn)程并執(zhí)?了不同的邏輯
關(guān)于fork:
當(dāng)程序調(diào)?fork函數(shù)時(shí),系統(tǒng)會(huì)創(chuàng)建新的進(jìn)程并為其分配資源;然后,會(huì)將原來進(jìn)程的相關(guān)內(nèi)容全部復(fù)制到新的進(jìn)程中。
fork()函數(shù)被調(diào)??次,但是會(huì)返回兩次(??進(jìn)程各?次)
返回值分析:
1)在?進(jìn)程 中,fork函數(shù)返回0
2)在?進(jìn)程中,fork函數(shù)返回新創(chuàng)建?進(jìn)程的ID
3)如果出現(xiàn)錯(cuò)誤,fork返回?個(gè)負(fù)值
(對(duì)1和2的原因分析:①在?進(jìn)程中通過調(diào)?getppid可以?便的知道?進(jìn)程的PID;②沒有?個(gè)函數(shù)可以使?進(jìn)程獲得其所有?進(jìn)程 的PID。(所以在fork返回時(shí),將?進(jìn)程的PID直接返回給?進(jìn)程))
特點(diǎn):
1. ?、?進(jìn)程共享正?段,不共享數(shù)據(jù)、堆、棧段,?進(jìn)程獲得?進(jìn)程數(shù)據(jù)、堆、棧段的副本。
2. ?進(jìn)程會(huì)獲得緩沖區(qū)的副本,即fork前進(jìn)程緩沖區(qū)中的數(shù)據(jù)未被flush掉,則fork后,?進(jìn)程能夠獲得?進(jìn)程緩沖區(qū)中的數(shù)據(jù)。
3. ?進(jìn)程所有被打開的?件描述符都會(huì)被復(fù)制到?進(jìn)程中。 注:fork之后處理?件描述符通常有兩種情況: ①?進(jìn)程等待?進(jìn)程結(jié)束; ②?、?進(jìn)程各?執(zhí)?不同的正?段(?、?進(jìn)程各?關(guān)閉不需要使?的?件描述符);
4. fork之后?、?進(jìn)程的區(qū)別: ①fork的返回值; ②進(jìn)程ID不同; ③?進(jìn)程也不同; ④?進(jìn)程的tms_utime、tms_stime、tms_cutime和tms_ustime均被設(shè)置為0; ⑤?進(jìn)程設(shè)置的?件鎖不會(huì)被?進(jìn)程繼承; ⑥?進(jìn)程的未處理的鬧鐘被清除; ⑦?進(jìn)程的未處理信號(hào)集設(shè)置為空集;
5. fork失敗的兩個(gè)主要原因: ①系統(tǒng)中進(jìn)程數(shù)?已經(jīng)達(dá)到上限; ②該實(shí)際?戶的進(jìn)程總數(shù)達(dá)到系統(tǒng)限制;?
13 使??法:
①?個(gè)進(jìn)程希望復(fù)制??,使得?、?進(jìn)程執(zhí)?不同的代碼段。如?進(jìn)程監(jiān)聽端?,收到消息后,fork出?進(jìn)程處理消息,?進(jìn)程仍 然負(fù)責(zé)監(jiān)聽消息。(?監(jiān)聽,?處理信息)
②?個(gè)進(jìn)程需要執(zhí)?另?個(gè)程序。如fork后執(zhí)??個(gè)shell命令。
分析init函數(shù),
其實(shí)在這?的話就是?進(jìn)程waitpid等待?進(jìn)程,?進(jìn)程執(zhí)?真正的邏輯 并且?進(jìn)程?了ptrace來反調(diào)試(?個(gè)進(jìn)程只能被?個(gè)進(jìn)程ptrace,如果你??調(diào)?ptarce,這樣其它程序就?法通過ptrace調(diào)試或者向 您的程序進(jìn)程注?代碼) 所以?調(diào)試器不能調(diào)試?進(jìn)程,ptrace的處理要么就是讓他不執(zhí)?,要么就是直接將其nop掉 但是我們這?就是要想辦法調(diào)試?進(jìn)程,最?便的?法就是直接在其fork創(chuàng)建?進(jìn)程之前,就ctrl+n強(qiáng)制設(shè)置rip跳轉(zhuǎn)到?進(jìn)程的邏輯執(zhí) ?
我ctrl+n沒起作用。。。
點(diǎn)進(jìn)去函數(shù)?
cbc模式的tea,data1和data2每次加密都會(huì)更新,且每次的更新都和我們的輸?有關(guān) 我們有最后的?較數(shù)據(jù),data1和data2只知道初始值,所以以這些條件我們能解開前8字節(jié)(cmp → reverse_tea → xor_with_data → inp) 然后我們實(shí)現(xiàn)?下正向的加密去更新data,就可以得到下?輪的data1和data2 從?以此類推的計(jì)算出每次加密的8個(gè)字節(jié) 先解開我們的前?個(gè)字節(jié)
先解開我們的前?個(gè)字節(jié)
#include <stdio.h> #include <stdint.h> uint32_t data1 = 0x5F797274; uint32_t data2 = 0x64726168; //初始的 data 值 void decrypt(uint32_t* v, uint32_t* k) { uint32_t delta = 0x9E3779B9; uint32_t v0 = v[0], v1 = v[1], sum = (delta * 32) & 0xffffffff, i; uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; for (i = 0; i < 32; i++) { v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3); v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1); sum -= delta; } v0 = v0 ^ data1; v1 = v1 ^ data2; v[0] = v0; v[1] = v1; 2021極客?挑戰(zhàn)逆向疑題講解 16 } int main() { uint32_t temp[2] = { 0xC9FA3B95, 0x7CFD0735 }; uint32_t key[4] = { 0x65766967, 0x756F795F, 0x7075635F, 0x6165745F }; int i = 0; decrypt(temp, key); printf("%c%c%c%c%c%c%c%c", *((char*)&temp[0] + 0), *((char*)&temp[0] + 1), *((char*)&temp[0] + 2), *((char*)&temp[0] + 3), *((char*)&temp return 0; }?最后的腳本
#include <stdio.h> #include <stdint.h> uint32_t data1 = 0x5F797274; uint32_t data2 = 0x64726168; //初始的data 值 void encrypt(uint32_t* v, uint32_t* k) { uint32_t v0 = v[0], v1 = v[1], sum = 0, i; data1 ^= v0; data2 ^= v1; v0 = data1; v1 = data2; uint32_t delta = 0x9E3779B9; uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; for (i = 0; i < 32; i++) { sum += delta; v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1); v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3); } data1 = v0; data2 = v1; } void decrypt(uint32_t* v, uint32_t* k) { uint32_t delta = 0x9E3779B9; uint32_t v0 = v[0], v1 = v[1], sum = (delta * 32) & 0xffffffff, i; uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; for (i = 0; i < 32; i++) { v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3); v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1); sum -= delta; } v0 = v0 ^ data1; v1 = v1 ^ data2; v[0] = v0; v[1] = v1; } 2021極客?挑戰(zhàn)逆向疑題講解 17 int main() { uint32_t array[] = { 0xC9FA3B95, 0x7CFD0735, 0x958C7C9F, 0xC143B59E, 0x61741E89, 0xF47DCDC4, 0xD6E2A1F2, 0x6A38E9AD, 0xC2C16FEB, 0x8C0EE99 uint32_t key[4] = { 0x65766967, 0x756F795F, 0x7075635F, 0x6165745F }; int i = 0; for (i = 0; i < 10; i += 2) { uint32_t temp[2]; temp[0] = array[i]; temp[1] = array[i + 1]; decrypt(temp, key); printf("%c%c%c%c%c%c%c%c", *((char*)&temp[0] + 0), *((char*)&temp[0] + 1), *((char*)&temp[0] + 2), *((char*)&temp[0] + 3), *((char*)&tem //更新data encrypt(temp, key); } //SYC{ySaySanDian_Zh0n_La_y1n_Cha_xIan} return 0; }總結(jié)
以上是生活随笔為你收集整理的Have a tea -(极客大挑战(SMC,fork的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。