国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁 > news >正文

智慧農(nóng)業(yè)網(wǎng)站建設(shè)網(wǎng)絡(luò)銷售

智慧農(nóng)業(yè)網(wǎng)站建設(shè),網(wǎng)絡(luò)銷售,大淘客構(gòu)建自己的網(wǎng)站,深圳網(wǎng)站建設(shè) 駿域網(wǎng)站建設(shè)hello everybody,本期是安卓逆向so層魔改md5教學(xué),干貨滿滿,可以細(xì)細(xì)品味,重點介紹的是so層魔改md5的處理. 常見的魔改md5有: 1:明文加密前處理 2:改初始化魔數(shù) 3:改k表中的值 4:改循環(huán)左移的次數(shù) 本期遇到的是124.且循環(huán)左移的次數(shù)是動態(tài)的,需要前面的加密結(jié)果處理生成 目錄…

hello everybody,本期是安卓逆向so層魔改md5教學(xué),干貨滿滿,可以細(xì)細(xì)品味,重點介紹的是so層魔改md5的處理.

常見的魔改md5有:

????????1:明文加密前處理 2:改初始化魔數(shù) 3:改k表中的值 4:改循環(huán)左移的次數(shù)? 本期遇到的是124.且循環(huán)左移的次數(shù)是動態(tài)的,需要前面的加密結(jié)果處理生成

目錄

首先介紹md5的實現(xiàn)

說明:

登陸抓包:

sign的加密

總結(jié):

首先介紹md5的實現(xiàn)

1首先對明文16進(jìn)制編碼,比如我的名字 楊如畫 會被編碼成?e6 9d a8 e5 a6 82 e7 94 bb

2把明文填充到448bit(比如e6是兩個16進(jìn)制字符,也就是一個字節(jié),8bit),填充方式是先填充一個80,接著一直填充00 00 00直到448bit,

填充成這樣e6 9d a8 e5 a6 82 e7 94 bb 80 00 00 00...(56個字節(jié),448bit)

3附加消息長度,需要填充8個字節(jié),也就是e6 9d a8 e5 a6 82 e7 94 bb的長度9個字節(jié),72位,長度就是72,轉(zhuǎn)成16進(jìn)制就是48,理論上填充的長度為48 也就是

00 00 00 00 00 00 00 48,但是md5處理的時候需要把這8個字節(jié)轉(zhuǎn)為小端序,什么是小端續(xù)呢?你可以上網(wǎng)查,我簡單說一下這里的小端序就是把這8個字節(jié),注意是以字節(jié)為單位把最后一個放到第一個,倒數(shù)第二個放到第二個,以此類推,最終結(jié)果是48?00 00 00 00 00 00 00.? md5的輸入長度是無限長的,如果64bit位放不下,也就是長度大于2的64次方的話,會取低64bit,也是按照小端序來取的.? 此外sha3算法也是明文無限長,其他hash算法不是.

4最終明文處理成e6 9d a8 e5 a6 82 e7 94 bb 80 00 00 00...48?00 00 00 00 00 00 00,一共512bit,如果輸入的數(shù)據(jù)剛好為448bit,那么就需要填充512bit,再加上附加消息長度64bit,一共1024bit,因為md5的分組長度為512bit,所以需要進(jìn)行分組處理

至于k表和初始化魔數(shù)和循環(huán)左移我們待會再說,先對md5的明文處理有一個概念,注意這很重要,后續(xù)需要用到.

概念介紹完了,我們來實戰(zhàn)吧

說明:

設(shè)備: pixel4 XL?android10

抓包:charles配合socksdroid

下載地址:aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzMwNjM5OS9oaXN0b3J5X3YzNjA=

frida版本:16.0.1

此版本是舊版本,新版本算法并沒有改,流程也大致差不多,復(fù)雜的話可以frida trace,后續(xù)也會介紹到,事實上這也是我為了逆這個算法現(xiàn)學(xué)的,介紹一下背景,我是學(xué)了frida rpc接觸到了這個app,當(dāng)時逆登陸的時候有個sign,當(dāng)時用的是rpc,因為rpc需要開著手機,我想著能不能逆向出完整的算法呢?這期間遇到了非常大的挑戰(zhàn),因為很多frida的api我也不太熟悉,我也是現(xiàn)學(xué)現(xiàn)用,后續(xù)會一一介紹,整個魔改md5耗時3天.

登陸抓包:

1 查詢參數(shù)沒什么特別的,重點看表單,username是手機號,密碼加密了,還有一個用作驗簽的sign,這個sign的作用我之前說過很多次了,他是用來驗簽的,通常是把查詢參數(shù)或者表單中的參數(shù)除sign之外的其他值拼接起來加密,防止數(shù)據(jù)包被惡意篡改,當(dāng)然也不是不能篡改,把這個sign逆了不就行了嗎

2 password的我就不說了,在java層,我直接給出代碼吧? 定位可以搜字符串,hook java層系統(tǒng)函數(shù)等等

# 128位密鑰
_str = hashlib.md5('16751641924'.encode('utf-8')).hexdigest()
key = _str[0:16].encode('utf-8')# 128位IV(Initialization Vector)
iv = 'yoloho_dayima!%_'.encode('utf-8')# 明文
plaintext = "1472580369Xx"  # 不能超過31個字符
# 加密
cipher = AES.new(key, AES.MODE_CBC, iv)
padded_data = pad(plaintext.encode(), AES.block_size)
ciphertext = cipher.encrypt(padded_data)# 將密文以Base64格式輸出
password = base64.b64encode(ciphertext).decode()
print(password)

sign的加密

3 定位我也不說了,搜字符串,hook什么hashmap,hashset,stringbuilder之類的你都試試吧,總能找到的,我就貼下面了

4 hook encrypt_data這個native函數(shù),返回的就是sign,直接右鍵復(fù)制為frida片段

5 有java的api 要包在Java.perform里?

Java.perform(function (){let Crypt = Java.use("com.yoloho.libcore.util.Crypt");
Crypt["encrypt_data"].implementation = function (j, str, j2) {console.log(`Crypt.encrypt_data is called: j=${j}, str=${str}, j2=${j2}`);let result = this["encrypt_data"](j, str, j2);console.log(`Crypt.encrypt_data result=${result}`);return result;
};
})

6 配合著抓包,點擊一下登陸,發(fā)現(xiàn)加密的結(jié)果與抓包中一樣,那鐵定是這里了

7 接下來為了避免一直手點登陸,可以進(jìn)行java層主動調(diào)用

function call(){Java.perform(function (){let Crypt = Java.use("com.yoloho.libcore.util.Crypt");
var res = Crypt["encrypt_data"](0, '23eedd78b2b95ef16b82da4fe2177bdcb1920dd6user/login16751641924oKc0ZztEbNCIcDKL3hoF/A==', 85)console.log(res);
})
}

8 我建議你采用我這個主動調(diào)用,這樣最終加密出來的結(jié)果會和我的一樣,方便你調(diào)試

9 接下來我們把libCrypt.so拖到ida32中反編譯,Crypt名字在上面的java代碼中出現(xiàn)了,只有32位的所以拖到ida32中

10 反編譯后搜一下java發(fā)現(xiàn)是靜態(tài)注冊,這里名字叫encrypt_1data是因為進(jìn)行了符號修飾

11 這里直接點進(jìn)去看內(nèi)部邏輯

12 轉(zhuǎn)換一下JNIEnv對象,ida7.5以后可以不用導(dǎo)頭文件,直接改類型

13 看到NewStringUTF,第一個參數(shù)是JNIEnv,第二個參數(shù)是CString,這里是把CString轉(zhuǎn)為JString再返回給java層,所以最終加密的結(jié)果就是v12

14 這里可以hook 1B88這個函數(shù),這種沒有名字的通常后面就是偏移量,不放心的話可以點進(jìn)去看看,加上so基值就可以得到函數(shù)內(nèi)存地址了,這是arm指令的,如果是thubm指令的就得+1,如果你不會看arm還是thumb指令就看so是32還是64,32的一般是thumb,64的一般是arm指令

15 接下來hook sub_1B88這個函數(shù),這是修改過后的,一開始你不知道哪些是地址就把所有參數(shù)打印一遍,是地址再dump,因為你dump數(shù)字的話是會報錯的

var soAddr = Module.findBaseAddress("libCrypt.so");
var funcAddr = soAddr.add(0x1B88+1)  //32位+1Interceptor.attach(funcAddr,{onEnter: function(args){console.log('onEnter arg[0]: ',args[0])console.log('onEnter arg[1]: ',args[1])console.log('onEnter arg[2]: ',hexdump(args[2]))console.log('onEnter arg[3]: ',args[3])console.log('onEnter arg[4]: ',args[4])console.log('onEnter arg[5]: ',args[5])console.log('onEnter arg[6]: ',args[6])this.arg2 = args[2]this.arg6 = args[6]},onLeave: function(retval){console.log('onLeave arg[2]: ',hexdump(this.arg2))console.log('onLeave arg[6]: ',hexdump(this.arg6))console.log('onLeave result: ',retval)}});

16這里開著兩個hook腳本,java層主動調(diào)用,分析so的結(jié)果,后面這張圖我就不貼了,就是java層的主動調(diào)用

17 我們可以看到結(jié)果在arg6中,也就是第7個參數(shù),證明結(jié)果確實來自v12

18 而arg2就是我們從java層傳進(jìn)的第二個明文參數(shù),只有這個是重要的,其他不重要的就不要輸出,影響判斷?

19 接下來我們從1B88點進(jìn)去看看,點進(jìn)去后發(fā)現(xiàn)這里面調(diào)用了很多函數(shù),我是把這些函數(shù)都hook了一般,但是感覺很亂,有好幾個函數(shù)被調(diào)用了好幾次,有的函數(shù)內(nèi)部有if判斷還有嵌套函數(shù),極大影響我們的思路,這里可以使用frida trace工具來幫我們分析調(diào)用流程

20 frida trace是github上的一個工具,可以自行去下載解壓后放到ida的plugis目錄下,重啟ida?

21 這里還有幾個好用的ida插件signsrch,findhash,可以識別一些加密特征來判斷是什么加密. 這里直接點一下traceNatives會生成一條命令,終端執(zhí)行一下?

22 接下來主動調(diào)用一下java層的函數(shù),它會給我們打印函數(shù)調(diào)用流程,這樣就清晰多了,這里的函數(shù)地址默認(rèn)都加了1,因為這個so是thumb指令的

23 我們上面分析到1B88,后面的函數(shù)你可以一一hook,到這里我感覺寫的內(nèi)容有點多了,我怕你們沒耐心看完,所以就不帶你們一個一個函數(shù)hook了

24 這個sub1105就是魔改的md5算法?

25 最終會加密3次md5,每一次md5都是魔改的,共同的魔改是這里傳進(jìn)去的都是md5 update的字節(jié),而且這個字節(jié)你實現(xiàn)的話必須要魔改原本的md5算法.除此以外,第一次還魔改了循環(huán)左移,第二次還魔改了初始化魔數(shù)和循環(huán)左移,并且初始化魔數(shù)并不是固定的,而是由第一次加密的md5結(jié)果處理生成的,第三次加密的字節(jié)需要由第二次加密的結(jié)果提供,也就是說,最終的加密結(jié)果需要依靠前兩次加密的

26 說完了這些我們直接開始hook,下面的代碼是簡化后的,略去了無效的輸出,方便閱讀

var soAddr = Module.findBaseAddress("libCrypt.so");
var funcAddr = soAddr.add(0x1104+1)  //32位+1var num = 0
Interceptor.attach(funcAddr,{onEnter: function(args){num+=1console.log(`===============${num}============================`)console.log('onEnter arg[0]: ',hexdump(args[0]))console.log('onEnter arg[1]: ',hexdump(args[1]))console.log('onEnter arg[2]: ',hexdump(args[2]))this.arg1 = args[1]},onLeave: function(retval){console.log('onLeave arg[1]: ',hexdump(this.arg1))}});

27 這里我結(jié)合ida中的代碼分析a1和a2,a3是什么

28 選中a1,發(fā)現(xiàn)它一直在被32減去它的一個值并賦值給另一個值,而復(fù)制的值參與了64輪加密

29 這里我們把減號改成加號再轉(zhuǎn)hex,接著對比著c++中的md5可以發(fā)現(xiàn)k值并沒有被魔改,7,12,17,22是循環(huán)左移的次數(shù),并且他是交替著的,我們發(fā)現(xiàn)下圖中的v82 v83 v6 v76也是交替著的,這也就意味著a1就是循環(huán)左移的次數(shù),循環(huán)左移你們可以上網(wǎng)搜索了解一下,?4個字節(jié)32位,它一直要被32減去的原因可能是他在循環(huán)右移,因為32字節(jié)的數(shù)左移一個數(shù)相當(dāng)于右移32減去這個數(shù)

30我們來看看傳進(jìn)去的3個a1參數(shù)長啥樣

31 第一組

32 第二組?

33 第三組,07 0c 11 16十進(jìn)制也就是07 12 17 22,這不就是循環(huán)左移的次數(shù)嗎,對比了下剩下的,發(fā)現(xiàn)第三個加密循環(huán)左移是標(biāo)準(zhǔn)的

34 如果你分不清是so層是循環(huán)左移還是右移那你可以拿這16個字節(jié)和被32減去的數(shù)值分別進(jìn)行加密,如果其他地方?jīng)]有被魔改,那么一定有一個是對的

好了,接下來看a2參數(shù),看到01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 這組數(shù)據(jù)你就應(yīng)該想到md5加密的4組初始化魔數(shù)

35 對比著C++中的md5,注意這里同樣是以4個字節(jié)進(jìn)行小端序排列

36 從so中的取值中也能判斷出來?

37 參數(shù)3是md5明文updata后的字節(jié),注意這是被填充過的,從終端可以看出

38 接下來分析3個魔改加密的實現(xiàn),我喜歡從后往前推

39 把看似明文的東西md5以下,發(fā)現(xiàn)結(jié)果是正確的,但你千萬不要覺得傳進(jìn)去的是明文,我上面圈了80 00 ...和c0 00 00 00 00 00 00 00,還記得前面介紹的填充和附加消息長度嗎,就是這兩個,所以傳進(jìn)去的是updata的字節(jié)!我前后強調(diào)很多遍了!!!

?40 那么接下來就應(yīng)該分析j79Yb6ILYA602iiagzMVUw==是哪來的 你不用想也知道這肯定是第二次的加密結(jié)果某種形式變化的

?

41 也就是說8f bf 58 6f a2 0b 60 0e b4 da 28 9a 83 33 15 53怎么變成j79Yb6ILYA602iiagzMVUw==的

42 大膽猜測一下,第二次加密和第三次加密前不是進(jìn)行了一堆函數(shù)操作嗎,當(dāng)然只有部分函數(shù)做了處理,還有一些加密的準(zhǔn)備工作

43 這里我就大膽猜測?

44 j79Yb6ILYA602iiagzMVUw==看著像base64,把它from base64一下看看

45 啥,亂碼?別急,轉(zhuǎn)16進(jìn)制看看,上面的?8f bf 58 6f a2 0b 60 0e b4 da 28 9a 83 33 15 53不就是16進(jìn)制的嗎,你猜怎么著?

46 結(jié)果很顯然了,?8f bf 58 6f a2 0b 60 0e b4 da 28 9a 83 33 15 53from hex 后to base64就是j79Yb6ILYA602iiagzMVUw==

47 所以接下來就清晰了,分析第二次加密

48 明文是0ZztEbNCIcDKL3hoF/A==,這是我們主動調(diào)用的加密字符串的一部分,那另一部分呢,等等,另一部分是64字節(jié),512bit,這不就是md5的分組長度嗎

49? 我們再來看看第一次加密的參數(shù),正是我們所說的前512bit

50 也就是說so把23eedd78b2b95ef16b82da4fe2177bdcb1920dd6user/login16751641924oKc0ZztEbNCIcDKL3hoF/A==,這整個字符串進(jìn)行updata和填充到1024bit,因為md5處理的字節(jié)必須是512的整數(shù)倍,并分了兩組,第一組由第一次加密得到,得到的結(jié)果做為第二次加密的初始化魔數(shù)傳入,并加密第二組的512bit得到第三次加密的16進(jìn)制參數(shù)

51好像是這樣,那怎么驗證呢,因為這兩次md5傳入的字節(jié)都不是完整的,相當(dāng)于讓我把一個字符串update得到的兩組512bit拆開加密,這該如何是好啊?

52 所以這就需要你對md5的加密流程足夠了解,你才能去改md5的源代碼來達(dá)到上面所說的效果,那我們先來看第一組加密的吧

53 這兩次加密的循環(huán)左移都需要改,這里我提前改了

/* Round 1 */
FF(a, b, c, d, x[0], 0, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], 1, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], 2, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], 3, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], 0, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], 1, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], 2, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], 3, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], 0, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], 1, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], 2, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], 3, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], 0, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], 1, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], 2, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], 3, 0x49b40821); /* 16 *//* Round 2 */
GG(a, b, c, d, x[1], 4, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], 5, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], 6, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], 7, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], 4, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], 5, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], 6, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], 7, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], 4, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], 5, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], 6, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], 7, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], 4, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], 5, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], 6, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], 7, 0x8d2a4c8a); /* 32 *//* Round 3 */
HH(a, b, c, d, x[5], 8, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], 9, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], 10, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], 11, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], 8, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], 9, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], 10, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], 11, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], 8, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], 9, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], 10, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], 11, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], 8, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], 9, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], 10, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], 11, 0xc4ac5665); /* 48 *//* Round 4 */
II(a, b, c, d, x[0], 12, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], 13, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], 14, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], 15, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], 12, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], 13, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], 14, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], 15, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], 12, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], 13, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], 14, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], 15, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], 12, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], 13, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], 14, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], 15, 0xeb86d391); /* 64 */

54 接下來我們需要做的事是把明文傳的23eedd78b2b95ef16b82da4fe2177bdcb1920dd6user/login16751641924oKc,最終MD5Encode的時候壓入的字節(jié)和下圖一樣即可

55 怎么操作呢,我直接說結(jié)論了,由于傳參剛好是512bit,所以只需要把填充和附加消息長度的地方注釋即可

56 最終結(jié)果也是成功得到了

57 接一下就是改第二次加密的初始化魔數(shù),可以仿照著01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 按小端字節(jié)序排列

58 接下來改updata的字節(jié)?

59 這里主要改小端字節(jié)序,為什么呢,因為填充的80是直接跟著明文的字節(jié),而小端字節(jié)序是有明文的長度決定的,注意這里的長度是整個長度,之前說過了,?

60? ? ? ? ? 00 00 00 00 00 00 02 a8? ? a8代表的是168bit,21字節(jié),正是0ZztEbNCIcDKL3hoF/A==的字符個數(shù),02代表的是512bit,64字節(jié),也就是前面的那串

61 c++md5中由于只有168字符,所以我們需要手動改消息長度的內(nèi)容,怎么改呢,很簡單 a8 00?00 00 00 00 00 00 改a8 02?00 00 00 00 00 00怎么改?

62 很簡單中間改bits的值就好了,加上一句bits[1]=2;

?63 結(jié)果也就驗證成功了,那么怎么寫活呢,結(jié)尾我會附上完整python代碼

總結(jié):

本次教學(xué)干貨很多,由于考慮單篇文章的閱讀時間,我省略了部分無關(guān)緊要的流程,核心流程都在里面了.

說實話寫這個sign算法的人水平很高,他對md5算法肯定是有充分了解和把握的,一般改改初始化魔數(shù),改改k值都很少見,他一個算法里連著改那么多算是比較少見了.

提一點,關(guān)于那個魔改的md5函數(shù),你可以結(jié)合著so層主動調(diào)用,不過你需要傳3個指針參數(shù),但是不太好構(gòu)造,我這里采取的是直接修改so層傳的第3個參數(shù)的值來驗證的(本文并未提及),如果沒有我上面說的前提,你自己摸索需要不斷進(jìn)行驗證推翻再驗證的過程,逆向就是這個樣子的.

本人寫作水平有限,如有講解不到位或者講解錯誤的地方,還請各位大佬在評論區(qū)多多指教,共同進(jìn)步,也可加本人微信lyaoyao__i(兩個_)

python代碼:

import struct
import base64
from loguru import logger
class sign():def __init__(self):passdef md5_1(self,message):def left_rotate(x, amount):return ((x << amount) | (x >> (32 - amount))) & 0xFFFFFFFFdef F(x, y, z):return (x & y) | (~x & z)def G(x, y, z):return (x & z) | (y & ~z)def H(x, y, z):return x ^ y ^ zdef I(x, y, z):return y ^ (x | ~z)def FF(a, b, c, d, x, s, ac):a = (a + F(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef GG(a, b, c, d, x, s, ac):a = (a + G(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef HH(a, b, c, d, x, s, ac):a = (a + H(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef II(a, b, c, d, x, s, ac):a = (a + I(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef pad_message(message):# original_length_bits = len(message) * 8# message += b'\x80'# while (len(message) + 8) % 64 != 0:#     message += b'\x00'# message += struct.pack('<Q', original_length_bits)    # 填充return messagea0 = 0x67452301b0 = 0xEFCDAB89c0 = 0x98BADCFEd0 = 0x10325476message = pad_message(message)chunks = [message[i:i+64] for i in range(0, len(message), 64)]for chunk in chunks:words = struct.unpack('<16I', chunk)A, B, C, D = a0, b0, c0, d0# Round 1A = FF(A, B, C, D, words[0], 0, 0xD76AA478)D = FF(D, A, B, C, words[1], 1, 0xE8C7B756)C = FF(C, D, A, B, words[2], 2, 0x242070DB)B = FF(B, C, D, A, words[3], 3, 0xC1BDCEEE)A = FF(A, B, C, D, words[4], 0, 0xF57C0FAF)D = FF(D, A, B, C, words[5], 1, 0x4787C62A)C = FF(C, D, A, B, words[6], 2, 0xA8304613)B = FF(B, C, D, A, words[7], 3, 0xFD469501)A = FF(A, B, C, D, words[8], 0, 0x698098D8)D = FF(D, A, B, C, words[9], 1, 0x8B44F7AF)C = FF(C, D, A, B, words[10], 2, 0xFFFF5BB1)B = FF(B, C, D, A, words[11], 3, 0x895CD7BE)A = FF(A, B, C, D, words[12], 0, 0x6B901122)D = FF(D, A, B, C, words[13], 1, 0xFD987193)C = FF(C, D, A, B, words[14], 2, 0xA679438E)B = FF(B, C, D, A, words[15], 3, 0x49B40821)# Round 2A = GG(A, B, C, D, words[1], 4, 0xF61E2562)D = GG(D, A, B, C, words[6], 5, 0xC040B340)C = GG(C, D, A, B, words[11], 6, 0x265E5A51)B = GG(B, C, D, A, words[0], 7, 0xE9B6C7AA)A = GG(A, B, C, D, words[5], 4, 0xD62F105D)D = GG(D, A, B, C, words[10], 5, 0x02441453)C = GG(C, D, A, B, words[15], 6, 0xD8A1E681)B = GG(B, C, D, A, words[4], 7, 0xE7D3FBC8)A = GG(A, B, C, D, words[9], 4, 0x21E1CDE6)D = GG(D, A, B, C, words[14], 5, 0xC33707D6)C = GG(C, D, A, B, words[3], 6, 0xF4D50D87)B = GG(B, C, D, A, words[8], 7, 0x455A14ED)A = GG(A, B, C, D, words[13], 4, 0xA9E3E905)D = GG(D, A, B, C, words[2], 5, 0xFCEFA3F8)C = GG(C, D, A, B, words[7], 6, 0x676F02D9)B = GG(B, C, D, A, words[12], 7, 0x8D2A4C8A)# Round 3A = HH(A, B, C, D, words[5], 8, 0xFFFA3942)D = HH(D, A, B, C, words[8], 9, 0x8771F681)C = HH(C, D, A, B, words[11], 10, 0x6D9D6122)B = HH(B, C, D, A, words[14], 11, 0xFDE5380C)A = HH(A, B, C, D, words[1], 8, 0xA4BEEA44)D = HH(D, A, B, C, words[4], 9, 0x4BDECFA9)C = HH(C, D, A, B, words[7], 10, 0xF6BB4B60)B = HH(B, C, D, A, words[10], 11, 0xBEBFBC70)A = HH(A, B, C, D, words[13], 8, 0x289B7EC6)D = HH(D, A, B, C, words[0], 9, 0xEAA127FA)C = HH(C, D, A, B, words[3], 10, 0xD4EF3085)B = HH(B, C, D, A, words[6], 11, 0x04881D05)A = HH(A, B, C, D, words[9], 8, 0xD9D4D039)D = HH(D, A, B, C, words[12], 9, 0xE6DB99E5)C = HH(C, D, A, B, words[15], 10, 0x1FA27CF8)B = HH(B, C, D, A, words[2], 11, 0xC4AC5665)# Round 4A = II(A, B, C, D, words[0], 12, 0xF4292244)D = II(D, A, B, C, words[7], 13, 0x432AFF97)C = II(C, D, A, B, words[14], 14, 0xAB9423A7)B = II(B, C, D, A, words[5], 15, 0xFC93A039)A = II(A, B, C, D, words[12], 12, 0x655B59C3)D = II(D, A, B, C, words[3], 13, 0x8F0CCC92)C = II(C, D, A, B, words[10], 14, 0xFFEFF47D)B = II(B, C, D, A, words[1], 15, 0x85845DD1)A = II(A, B, C, D, words[8], 12, 0x6FA87E4F)D = II(D, A, B, C, words[15], 13, 0xFE2CE6E0)C = II(C, D, A, B, words[6], 14, 0xA3014314)B = II(B, C, D, A, words[13], 15, 0x4E0811A1)A = II(A, B, C, D, words[4], 12, 0xF7537E82)D = II(D, A, B, C, words[11], 13, 0xBD3AF235)C = II(C, D, A, B, words[2], 14, 0x2AD7D2BB)B = II(B, C, D, A, words[9], 15, 0xEB86D391)a0 = (a0 + A) & 0xFFFFFFFFb0 = (b0 + B) & 0xFFFFFFFFc0 = (c0 + C) & 0xFFFFFFFFd0 = (d0 + D) & 0xFFFFFFFFresult = struct.pack('<4I', a0, b0, c0, d0)return result.hex()def md5_2(self,message,_result,length):def left_rotate(x, amount):return ((x << amount) | (x >> (32 - amount))) & 0xFFFFFFFFdef F(x, y, z):return (x & y) | (~x & z)def G(x, y, z):return (x & z) | (y & ~z)def H(x, y, z):return x ^ y ^ zdef I(x, y, z):return y ^ (x | ~z)def FF(a, b, c, d, x, s, ac):a = (a + F(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef GG(a, b, c, d, x, s, ac):a = (a + G(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef HH(a, b, c, d, x, s, ac):a = (a + H(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef II(a, b, c, d, x, s, ac):a = (a + I(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef pad_message(message):original_length_bits = len(message) * 8message += b'\x80'while (len(message) + 8) % 64 != 0:message += b'\x00'message += struct.pack('<Q', original_length_bits)return messagea0 = int(hex(_result[0]), 16)b0 = int(hex(_result[1]), 16)c0 = int(hex(_result[2]), 16)d0 = int(hex(_result[3]), 16)message = pad_message(message)   #448 255if(length<256):# 1組就一個_hex= hex(length)index_to_replace = message.rindex(bytes.fromhex(_hex[2:]))# 將目標(biāo)位置替換為 0x02message = message[:index_to_replace + 1] + b'\x02' + message[index_to_replace + 2:]else:_hex = hex(length-256)index_to_replace = message.rindex(bytes.fromhex(_hex[2:]))# 將目標(biāo)位置替換為 0x03message = message[:index_to_replace + 1] + b'\x03' + message[index_to_replace + 2:]chunks = [message[i:i+64] for i in range(0, len(message), 64)]for chunk in chunks:words = struct.unpack('<16I', chunk)A, B, C, D = a0, b0, c0, d0# Round 1A = FF(A, B, C, D, words[0], 0, 0xD76AA478)D = FF(D, A, B, C, words[1], 1, 0xE8C7B756)C = FF(C, D, A, B, words[2], 2, 0x242070DB)B = FF(B, C, D, A, words[3], 3, 0xC1BDCEEE)A = FF(A, B, C, D, words[4], 0, 0xF57C0FAF)D = FF(D, A, B, C, words[5], 1, 0x4787C62A)C = FF(C, D, A, B, words[6], 2, 0xA8304613)B = FF(B, C, D, A, words[7], 3, 0xFD469501)A = FF(A, B, C, D, words[8], 0, 0x698098D8)D = FF(D, A, B, C, words[9], 1, 0x8B44F7AF)C = FF(C, D, A, B, words[10], 2, 0xFFFF5BB1)B = FF(B, C, D, A, words[11], 3, 0x895CD7BE)A = FF(A, B, C, D, words[12], 0, 0x6B901122)D = FF(D, A, B, C, words[13], 1, 0xFD987193)C = FF(C, D, A, B, words[14], 2, 0xA679438E)B = FF(B, C, D, A, words[15], 3, 0x49B40821)# Round 2A = GG(A, B, C, D, words[1], 4, 0xF61E2562)D = GG(D, A, B, C, words[6], 5, 0xC040B340)C = GG(C, D, A, B, words[11], 6, 0x265E5A51)B = GG(B, C, D, A, words[0], 7, 0xE9B6C7AA)A = GG(A, B, C, D, words[5], 4, 0xD62F105D)D = GG(D, A, B, C, words[10], 5, 0x02441453)C = GG(C, D, A, B, words[15], 6, 0xD8A1E681)B = GG(B, C, D, A, words[4], 7, 0xE7D3FBC8)A = GG(A, B, C, D, words[9], 4, 0x21E1CDE6)D = GG(D, A, B, C, words[14], 5, 0xC33707D6)C = GG(C, D, A, B, words[3], 6, 0xF4D50D87)B = GG(B, C, D, A, words[8], 7, 0x455A14ED)A = GG(A, B, C, D, words[13], 4, 0xA9E3E905)D = GG(D, A, B, C, words[2], 5, 0xFCEFA3F8)C = GG(C, D, A, B, words[7], 6, 0x676F02D9)B = GG(B, C, D, A, words[12], 7, 0x8D2A4C8A)# Round 3A = HH(A, B, C, D, words[5], 8, 0xFFFA3942)D = HH(D, A, B, C, words[8], 9, 0x8771F681)C = HH(C, D, A, B, words[11], 10, 0x6D9D6122)B = HH(B, C, D, A, words[14], 11, 0xFDE5380C)A = HH(A, B, C, D, words[1], 8, 0xA4BEEA44)D = HH(D, A, B, C, words[4], 9, 0x4BDECFA9)C = HH(C, D, A, B, words[7], 10, 0xF6BB4B60)B = HH(B, C, D, A, words[10], 11, 0xBEBFBC70)A = HH(A, B, C, D, words[13], 8, 0x289B7EC6)D = HH(D, A, B, C, words[0], 9, 0xEAA127FA)C = HH(C, D, A, B, words[3], 10, 0xD4EF3085)B = HH(B, C, D, A, words[6], 11, 0x04881D05)A = HH(A, B, C, D, words[9], 8, 0xD9D4D039)D = HH(D, A, B, C, words[12], 9, 0xE6DB99E5)C = HH(C, D, A, B, words[15], 10, 0x1FA27CF8)B = HH(B, C, D, A, words[2], 11, 0xC4AC5665)# Round 4A = II(A, B, C, D, words[0], 12, 0xF4292244)D = II(D, A, B, C, words[7], 13, 0x432AFF97)C = II(C, D, A, B, words[14], 14, 0xAB9423A7)B = II(B, C, D, A, words[5], 15, 0xFC93A039)A = II(A, B, C, D, words[12], 12, 0x655B59C3)D = II(D, A, B, C, words[3], 13, 0x8F0CCC92)C = II(C, D, A, B, words[10], 14, 0xFFEFF47D)B = II(B, C, D, A, words[1], 15, 0x85845DD1)A = II(A, B, C, D, words[8], 12, 0x6FA87E4F)D = II(D, A, B, C, words[15], 13, 0xFE2CE6E0)C = II(C, D, A, B, words[6], 14, 0xA3014314)B = II(B, C, D, A, words[13], 15, 0x4E0811A1)A = II(A, B, C, D, words[4], 12, 0xF7537E82)D = II(D, A, B, C, words[11], 13, 0xBD3AF235)C = II(C, D, A, B, words[2], 14, 0x2AD7D2BB)B = II(B, C, D, A, words[9], 15, 0xEB86D391)a0 = (a0 + A) & 0xFFFFFFFFb0 = (b0 + B) & 0xFFFFFFFFc0 = (c0 + C) & 0xFFFFFFFFd0 = (d0 + D) & 0xFFFFFFFFresult = struct.pack('<4I', a0, b0, c0, d0)return result.hex()def md5_3(self,message):def left_rotate(x, amount):return ((x << amount) | (x >> (32 - amount))) & 0xFFFFFFFFdef F(x, y, z):return (x & y) | (~x & z)def G(x, y, z):return (x & z) | (y & ~z)def H(x, y, z):return x ^ y ^ zdef I(x, y, z):return y ^ (x | ~z)def FF(a, b, c, d, x, s, ac):a = (a + F(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef GG(a, b, c, d, x, s, ac):a = (a + G(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef HH(a, b, c, d, x, s, ac):a = (a + H(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef II(a, b, c, d, x, s, ac):a = (a + I(b, c, d) + x + ac) & 0xFFFFFFFFreturn left_rotate(a, s) + b & 0xFFFFFFFFdef pad_message(message):original_length_bits = len(message) * 8message += b'\x80'while (len(message) + 8) % 64 != 0:message += b'\x00'message += struct.pack('<Q', original_length_bits)return messagea0 = 0x67452301b0 = 0xEFCDAB89c0 = 0x98BADCFEd0 = 0x10325476message = pad_message(message)chunks = [message[i:i+64] for i in range(0, len(message), 64)]for chunk in chunks:words = struct.unpack('<16I', chunk)A, B, C, D = a0, b0, c0, d0# Round 1A = FF(A, B, C, D, words[0], 7, 0xD76AA478)D = FF(D, A, B, C, words[1], 12, 0xE8C7B756)C = FF(C, D, A, B, words[2], 17, 0x242070DB)B = FF(B, C, D, A, words[3], 22, 0xC1BDCEEE)A = FF(A, B, C, D, words[4], 7, 0xF57C0FAF)D = FF(D, A, B, C, words[5], 12, 0x4787C62A)C = FF(C, D, A, B, words[6], 17, 0xA8304613)B = FF(B, C, D, A, words[7], 22, 0xFD469501)A = FF(A, B, C, D, words[8], 7, 0x698098D8)D = FF(D, A, B, C, words[9], 12, 0x8B44F7AF)C = FF(C, D, A, B, words[10], 17, 0xFFFF5BB1)B = FF(B, C, D, A, words[11], 22, 0x895CD7BE)A = FF(A, B, C, D, words[12], 7, 0x6B901122)D = FF(D, A, B, C, words[13], 12, 0xFD987193)C = FF(C, D, A, B, words[14], 17, 0xA679438E)B = FF(B, C, D, A, words[15], 22, 0x49B40821)# Round 2A = GG(A, B, C, D, words[1], 5, 0xF61E2562)D = GG(D, A, B, C, words[6], 9, 0xC040B340)C = GG(C, D, A, B, words[11], 14, 0x265E5A51)B = GG(B, C, D, A, words[0], 20, 0xE9B6C7AA)A = GG(A, B, C, D, words[5], 5, 0xD62F105D)D = GG(D, A, B, C, words[10], 9, 0x02441453)C = GG(C, D, A, B, words[15], 14, 0xD8A1E681)B = GG(B, C, D, A, words[4], 20, 0xE7D3FBC8)A = GG(A, B, C, D, words[9], 5, 0x21E1CDE6)D = GG(D, A, B, C, words[14], 9, 0xC33707D6)C = GG(C, D, A, B, words[3], 14, 0xF4D50D87)B = GG(B, C, D, A, words[8], 20, 0x455A14ED)A = GG(A, B, C, D, words[13], 5, 0xA9E3E905)D = GG(D, A, B, C, words[2], 9, 0xFCEFA3F8)C = GG(C, D, A, B, words[7], 14, 0x676F02D9)B = GG(B, C, D, A, words[12], 20, 0x8D2A4C8A)# Round 3A = HH(A, B, C, D, words[5], 4, 0xFFFA3942)D = HH(D, A, B, C, words[8], 11, 0x8771F681)C = HH(C, D, A, B, words[11], 16, 0x6D9D6122)B = HH(B, C, D, A, words[14], 23, 0xFDE5380C)A = HH(A, B, C, D, words[1], 4, 0xA4BEEA44)D = HH(D, A, B, C, words[4], 11, 0x4BDECFA9)C = HH(C, D, A, B, words[7], 16, 0xF6BB4B60)B = HH(B, C, D, A, words[10], 23, 0xBEBFBC70)A = HH(A, B, C, D, words[13], 4, 0x289B7EC6)D = HH(D, A, B, C, words[0], 11, 0xEAA127FA)C = HH(C, D, A, B, words[3], 16, 0xD4EF3085)B = HH(B, C, D, A, words[6], 23, 0x04881D05)A = HH(A, B, C, D, words[9], 4, 0xD9D4D039)D = HH(D, A, B, C, words[12], 11, 0xE6DB99E5)C = HH(C, D, A, B, words[15], 16, 0x1FA27CF8)B = HH(B, C, D, A, words[2], 23, 0xC4AC5665)# Round 4A = II(A, B, C, D, words[0], 6, 0xF4292244)D = II(D, A, B, C, words[7], 10, 0x432AFF97)C = II(C, D, A, B, words[14], 15, 0xAB9423A7)B = II(B, C, D, A, words[5], 21, 0xFC93A039)A = II(A, B, C, D, words[12], 6, 0x655B59C3)D = II(D, A, B, C, words[3], 10, 0x8F0CCC92)C = II(C, D, A, B, words[10], 15, 0xFFEFF47D)B = II(B, C, D, A, words[1], 21, 0x85845DD1)A = II(A, B, C, D, words[8], 6, 0x6FA87E4F)D = II(D, A, B, C, words[15], 10, 0xFE2CE6E0)C = II(C, D, A, B, words[6], 15, 0xA3014314)B = II(B, C, D, A, words[13], 21, 0x4E0811A1)A = II(A, B, C, D, words[4], 6, 0xF7537E82)D = II(D, A, B, C, words[11], 10, 0xBD3AF235)C = II(C, D, A, B, words[2], 15, 0x2AD7D2BB)B = II(B, C, D, A, words[9], 21, 0xEB86D391)a0 = (a0 + A) & 0xFFFFFFFFb0 = (b0 + B) & 0xFFFFFFFFc0 = (c0 + C) & 0xFFFFFFFFd0 = (d0 + D) & 0xFFFFFFFFresult = struct.pack('<4I', a0, b0, c0, d0)return result.hex()def main(self,_str):str1 = _str[:64]str2 = _str[64:]# 示例用法res1 = self.md5_1(str1.encode('utf-8'))logger.info(f'第一次md5初始化魔數(shù)分割前的加密結(jié)果==>{res1}')# 將原始哈希字符串轉(zhuǎn)換為字節(jié)對象original_bytes = bytes.fromhex(res1)# 使用 struct 模塊按照規(guī)律解析字節(jié)對象并生成新的四組_result = [struct.unpack('<I', original_bytes[i:i + 4])[0] for i in range(0, len(original_bytes), 4)]logger.info(f'初始化魔數(shù)==>a1={hex(_result[0])}  a2={hex(_result[1])}  a3={hex(_result[2])}  a4={hex(_result[3])}')res2 = self.md5_2(str2.encode('utf-8'),_result,len(str2)*8)res_2 = base64.b64encode(bytes.fromhex(res2)).decode('utf-8')logger.info(f'第二次md5結(jié)果==>{res2},是最終加密結(jié)果的明文')sign = self.md5_3(res_2.encode('utf-8'))logger.info(f'第三次md5最終sign結(jié)果==>{sign}')obj = sign()
obj.main('23eedd78b2b95ef16b82da4fe2177bdcb1920dd6user/login16751641924oKc0ZztEbNCIcDKL3hoF/A==')

http://aloenet.com.cn/news/42243.html

相關(guān)文章:

  • 天河做網(wǎng)站設(shè)計一個新產(chǎn)品怎么推廣
  • 免費b2b網(wǎng)站推廣嘿嘿2023年最新新聞?wù)?/a>
  • 手機端網(wǎng)站提交表單驗證代碼畢節(jié)地seo
  • 建設(shè)網(wǎng)站所有步驟蘇州百度
  • 蘇州專門網(wǎng)站線上推廣方案
  • 做非物質(zhì)文化遺產(chǎn)網(wǎng)站的風(fēng)險長沙優(yōu)化排名
  • 互聯(lián)網(wǎng)開網(wǎng)站怎么做企業(yè)網(wǎng)站建設(shè)的作用
  • 網(wǎng)站建設(shè)后期維護(hù)個人在線網(wǎng)站推廣
  • 方正集團(tuán)網(wǎng)站是誰做的電腦培訓(xùn)網(wǎng)上免費課程
  • 中國科協(xié)網(wǎng)站建設(shè)招標(biāo)游戲推廣是什么工作
  • 開通網(wǎng)站后今天國內(nèi)新聞
  • 網(wǎng)站地圖做計劃任務(wù)seo搜索引擎優(yōu)化人才
  • 江蘇省建設(shè)招標(biāo)網(wǎng)站首頁阿里云域名查詢和注冊
  • 網(wǎng)站備案org甘肅百度推廣電話
  • 深圳門戶網(wǎng)站建設(shè)方案搜索引擎營銷的案例有哪些
  • 找人做網(wǎng)站價格鄭州seo網(wǎng)絡(luò)營銷
  • 響應(yīng)式自適應(yīng)網(wǎng)站模板杭州seo培訓(xùn)
  • 嘉興網(wǎng)站建設(shè)下載app
  • 深圳人才市場招聘網(wǎng)最新招聘信息疫情二十條優(yōu)化措施
  • 個人網(wǎng)站做淘寶客教程網(wǎng)絡(luò)營銷課程培訓(xùn)課程
  • 鄂爾多斯網(wǎng)站建設(shè)高端大氣網(wǎng)站建設(shè)
  • 濟(jì)南建設(shè)委員會網(wǎng)站網(wǎng)站收錄一鍵提交
  • 2022中國互聯(lián)網(wǎng)公司排名網(wǎng)站seo置頂 樂云踐新專家
  • 網(wǎng)站開發(fā)圖片建站公司網(wǎng)站源碼
  • 裝修推薦平臺星沙網(wǎng)站優(yōu)化seo
  • 百度不收錄手機網(wǎng)站嗎微信小程序開發(fā)一個多少錢啊
  • 沒有網(wǎng)站可以域名備案嗎西安網(wǎng)站seo診斷
  • 中國做的最好的網(wǎng)站有哪些百度競價托管公司
  • 西安那里做網(wǎng)站wordpress外貿(mào)獨立站
  • 百度網(wǎng)站上傳平面設(shè)計網(wǎng)站