摘要:逆向中常常出現(xiàn)一些加密算法,如果我們能對(duì)這些加密算法進(jìn)行快速識(shí)別則會(huì)大大減少我們逆向的難度,雖然已有密碼分析神器,但掌握手動(dòng)分析方法能幫助我們應(yīng)對(duì)更多的情況。這篇文章將介紹逆向中常見的單項(xiàng)散列算法和對(duì)稱加密算法的識(shí)別方法。
逆向中常常出現(xiàn)一些加密算法,如果我們能對(duì)這些加密算法進(jìn)行快速識(shí)別則會(huì)大大減少我們逆向的難度,雖然IDA已有密碼分析神器Findcrypt,但掌握手動(dòng)分析方法能幫助我們應(yīng)對(duì)更多的情況。這篇文章將介紹逆向中常見的單項(xiàng)散列算法和對(duì)稱加密算法的識(shí)別方法。
在很長(zhǎng)一段時(shí)間里我經(jīng)常發(fā)現(xiàn)自己面對(duì)復(fù)雜的加密算法無(wú)從下手,可能是因?yàn)檫€沒有系統(tǒng)學(xué)過(guò)密碼學(xué)吧orz,總之這個(gè)問(wèn)題困擾了我很久。于是最近我花了一些時(shí)間來(lái)解決自己在密碼學(xué)這塊的薄弱點(diǎn),寫下這篇文章的目的之一也是為了鞏固所學(xué)知識(shí)。
加密算法的部分沒有涉及公鑰加密算法(因?yàn)槲也粫?huì)hh)。每個(gè)算法都有一個(gè)例子,這些例子出自《加密與解密(第4版)》第6章的隨書附帶文件和各大比賽中的題目。
單向散列算法:
對(duì)稱加密算法:
MD5(Message Digest Algorithm)消息摘要算法對(duì)輸入的任意長(zhǎng)度的消息進(jìn)行運(yùn)算,產(chǎn)生一個(gè)128位的消息摘要。
MD5的特征是會(huì)出現(xiàn)下圖中?A,B,C,D?這四個(gè)常量。
這里我們直接用《加密與解密(第4版)》隨書文件MD5KeyGenMe.exe來(lái)分析。
在導(dǎo)入表中找到GetDlgItemTextA函數(shù)定位關(guān)鍵代碼,兩次GetDlgItemTextA函數(shù)讀取的應(yīng)該分別是Name和Serial Number:
sub_4012B0函數(shù)我們點(diǎn)進(jìn)去看看發(fā)現(xiàn)了MD5的幾個(gè)特征常量:
還原一下符號(hào),需要注意的一點(diǎn)是連續(xù)調(diào)用兩次MD5_Update相當(dāng)于把兩次的輸入拼接后調(diào)用一次MD5_Update的結(jié)果:
寫出注冊(cè)機(jī):
from hashlib import md5 name = b"pediy"digest = md5(name + b"www.pediy.com").digest()a2345 = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"serial_number = ""for b in digest: serial_number += a2345[b % 32]print(f"Serial Number("{name}")={serial_number[0:4]}-{serial_number[4:8]}-{serial_number[8:12]}-{serial_number[12:16]}")
Findcrypt插件能幫助我們快速找到這些常量,不過(guò)這里還是著重講手動(dòng)分析的方法。
安全散列算法(Secure Hash Algorithm,SHA)包括SHA-1、SHA-256、SHA-384和SHA-512,分別產(chǎn)生160位、256位、384位和512位的散列值。
類似于MD5,SHA算法使用了一系列的常數(shù):
還是用隨書文件SHA1KeyGenMe.exe來(lái)分析。
還是先通過(guò)導(dǎo)入表定位關(guān)鍵代碼:
發(fā)現(xiàn)sub_401000函數(shù)中出現(xiàn)了SHA1算法用到的常量:
還原下符號(hào):
寫出注冊(cè)機(jī):
from hashlib import sha1 name = b"pediy"digest = sha1(name).digest()aPEDIY = b"PEDIY Forum"apediy = b"pediy.com"key = bytearray(digest)for i in range(11): key[i] ^= aPEDIY[i]for i in range(12,17): key[i] ^= key[i - 12]for i in range(17,20): key[i] ^= apediy[i - 17]serial_number = ""for i in range(10): serial_number += hex(key[i] ^ key[i + 10])[2:].zfill(2).upper()print(serial_number)
RC4是一種比較簡(jiǎn)單的流密碼,該算法雖然沒有用到特征常量,但是特征也比較容易識(shí)別。
分析RC4 Sample.exe文件。
還是通過(guò)導(dǎo)入表找到關(guān)鍵代碼:
?sub_401000函數(shù)明顯具有RC4密鑰調(diào)度算法(KSA)的特征:
sub_401070函數(shù)是RC4算法的第二步:
TEA算法是分組密碼,分組長(zhǎng)度為64位,密鑰長(zhǎng)度為128位,采用Feistel網(wǎng)絡(luò)。
其加密過(guò)程也非常簡(jiǎn)單,下面的代碼摘自Wikipedia:
#include void encrypt (uint32_t v[2], const uint32_t k[4]) { uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */ uint32_t delta=0x9E3779B9; /* a key schedule constant */ uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */ for (i=0; i<32; i++) { /* basic cycle start */ sum += delta; v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); } /* end cycle */ v[0]=v0; v[1]=v1;}
其中特征常量delta是由黃金分割點(diǎn)得來(lái)的,delta = 0x9E377989。TEA的變體XTEA和XXTEA都用到了這個(gè)常量,但是加密過(guò)程不同,在識(shí)別算法時(shí)需要注意。
在加密輪數(shù)方面,作者推薦的加密輪數(shù)是64輪,即循環(huán)32次,也可以采用其他加密輪數(shù),比如32輪或者128輪,在分析的時(shí)候也需要注意。
補(bǔ)充Wikipedia上的一些資料:
分析TEAKeyGenMe.exe:
sub_401380函數(shù)中出現(xiàn)了MD5特征常量:
sub_401000函數(shù)中出現(xiàn)了TEA特征常量,明顯為TEA算法:
整個(gè)加密過(guò)程是先取MD5(name)的前8個(gè)字節(jié)作為密鑰對(duì)序列號(hào)進(jìn)行TEA加密,加密的結(jié)果再與與MD5(name)的前8個(gè)字節(jié)異或,異或的結(jié)果與MD5的后8個(gè)字節(jié)比較。
寫出注冊(cè)機(jī):
from hashlib import md5from binascii import b2a_hexfrom pytea import TEA name = b"pediy"md5_digest = md5(name).digest()buf = bytearray(md5_digest[0:8])for i in range(8): buf[i] ^= md5_digest[i + 8]tea = TEA(md5_digest)print(f"Serial Number("{name.decode()}"): {b2a_hex(tea.Decrypt(buf)).decode().upper()}")
我在網(wǎng)上找了半天也沒找到個(gè)好用的TEA的Python實(shí)現(xiàn),干脆自己寫了個(gè):已上傳GitHub
DES全稱為Data Encryption Standard,即數(shù)據(jù)加密標(biāo)準(zhǔn),是一種使用密鑰加密的分組算法。
DES同前面的TEA一樣,都采用了Feistel網(wǎng)絡(luò),其加密過(guò)程可以用以下兩個(gè)圖表示:
Figure 1— The overall Feistel structure of DES
Figure 2—The Feistel function (F-function) of DES
圖一中的IP和FP分別代表初始置換(Initial Permutation)和末尾置換(Final Permutation),圖二中的S1到S8是8個(gè)置換盒(Substitution-Box),這些都可以作為識(shí)別DES算法的特征。
隨便在GitHub上扒一份源碼,就能找到這些常量:
int S1[] = {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}; int S2[] = {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}; int S3[] = {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}; int S4[] = { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}; int S5[] = { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}; int S6[] = {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}; int S7[] = { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}; int S8[] = {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11};
在2020祥云杯的某道APK逆向里,F(xiàn)indcrypt插件失效(可能是Findcrypt分析不了ARM框架下的文件),所以我們只能靠手動(dòng)分析找到DES的特征(以下是S1到S8):
還有一些別的特征,都可以幫助我們快速識(shí)別DES算法:
AES(Advanced Encryption Standard,高級(jí)加密標(biāo)準(zhǔn))是用于代替DES的新一代加密標(biāo)準(zhǔn)。AES具有128比特的分組長(zhǎng)度,支持128比特、192比特和256比特的密鑰長(zhǎng)度。
AES的加密過(guò)程:
SubBytes函數(shù):
我們識(shí)別AES的方法就是找到AES的SubBytes函數(shù)中使用的這個(gè)S-box。
在GitHub上扒一份源碼:
/* * S-box transformation table */static uint8_t s_box[256] = { // 0 1 2 3 4 5 6 7 8 9 a b c d e f 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, // 0 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, // 1 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, // 2 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, // 3 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, // 4 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, // 5 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, // 6 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, // 7 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, // 8 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, // 9 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, // a 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, // b 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, // c 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, // d 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, // e 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};// f /* * Inverse S-box transformation table */static uint8_t inv_s_box[256] = { // 0 1 2 3 4 5 6 7 8 9 a b c d e f 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, // 0 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, // 1 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, // 2 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, // 3 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, // 4 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, // 5 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, // 6 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, // 7 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, // 8 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, // 9 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, // a 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, // b 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, // c 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, // d 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, // e 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};// f
下面分析AESKeyGenMe.exe文件。
初步分析關(guān)鍵代碼:
?
在sub_401EC0函數(shù)中找到AES的S_box和S_box的逆,基本確定是AES加密,沒有找到iv,推測(cè)是ECB模式:
密鑰:
寫出注冊(cè)機(jī):
from hashlib import md5from Crypto.Cipher import AESfrom binascii import b2a_hex name = b"pediy"md5_digest = md5(name).digest()aes = AES.new(key=b"/x2B/x7E/x15/x16/x28/xAE/xD2/xA6/xAB/xF7/x15/x88/x09/xCF/x4F/x3C",mode=AES.MODE_ECB)dec = aes.decrypt(md5_digest)print(f"Serial Number("{name.decode()}")={b2a_hex(dec).decode().upper()}")
SM4是國(guó)密算法,由國(guó)家密碼局發(fā)布。SM4是一個(gè)分組算法,分組長(zhǎng)度為128比特,密鑰長(zhǎng)度為128比特,其結(jié)構(gòu)是Fesitel網(wǎng)絡(luò)的一個(gè)變體。
我們識(shí)別SM4算法的方法同樣是找到SM4的S-box(在GitHub上找的源碼):
static const unsigned char SboxTable[16][16] ={ {0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05}, {0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99}, {0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62}, {0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6}, {0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8}, {0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35}, {0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87}, {0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e}, {0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1}, {0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3}, {0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f}, {0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51}, {0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8}, {0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0}, {0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84}, {0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48}};
拿2020縱橫杯的第一道逆向題friendlyRE舉例。
我們直接找到關(guān)鍵代碼,這里是比較了Str1和Str2,通過(guò)交叉引用可以確定Str2加密過(guò)程,Str2為"2NI5JKCBI5Hyva+8AZa3mq!!":
再去找Str1的加密過(guò)程,發(fā)現(xiàn)有個(gè)地方用到了Base64表:
并且表是變換過(guò)的,第一次是大小寫互換,第二次相當(dāng)于是把表的前32位和后32位互換:
繼續(xù)找找到了SM4的S-box:
找到key:
整個(gè)過(guò)程大概就是把輸入經(jīng)過(guò)SM4加密之后再經(jīng)過(guò)一個(gè)變表的BASE64再與"2NI5JKCBI5Hyva+8AZa3mq!!"比較,寫出exp:
import base64from binascii import b2a_hex, a2b_hexfrom gmssl.sm4 import CryptSM4, SM4_DECRYPT BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"BASE64_change = (BASE64[32:] + BASE64[:32]).swapcase()table = str.maketrans(BASE64_change,BASE64)Str2 = "N25IKJBC5IyHav8+ZA3aqm!!"target = ""for i in range(0,len(Str2),2): target += Str2[i + 1] target += Str2[i]target = target.translate(table).replace("!","=")base64_decode = base64.b64decode(target)print(b2a_hex(base64_decode))crypt_sm4 = CryptSM4()crypt_sm4.set_key(b"Thisisinsteresth",SM4_DECRYPT)flag = crypt_sm4.crypt_ecb(base64_decode)print(b2a_hex(flag))
理論上是可以這么寫,但是gmssl庫(kù)的SM4的padding方式跟題目里SM4的padding方式不一致,導(dǎo)致無(wú)法解密。
所以換工具解密:
Hex2Str,得到最后的flag為:DoyouKnowVEHSEH!
ChaCha系列流密碼,作為Salsa密碼的改良版,具有更強(qiáng)的抵抗密碼分析攻擊的特性,“20”表示該算法有20輪的加密計(jì)算。
ChaCha20有一個(gè)初始矩陣,矩陣的輸入為一個(gè)256位的密鑰、64位隨機(jī)數(shù)、64位計(jì)數(shù)器值以及4×32位的常數(shù),它們均填充在32位整型數(shù)組中作為初始矩陣。排列方式如下:
四個(gè)常數(shù)0x61707865 0x3320646e 0x79622d32 0x6b206574按小端存儲(chǔ)轉(zhuǎn)為ASCII字符是"expand 32-byte k",這是我們用來(lái)識(shí)別ChaCha20算法的主要特征。
分析今年年初*CTF的一道題Favourite Architecure flag0,riscv架構(gòu)的文件只能用Ghirda分析。由于未知原因main函數(shù)的反匯編失效了,只能手?jǐn)]匯編。
我們直接從打印錯(cuò)誤的代碼開始分析,有兩個(gè)大跳轉(zhuǎn)跳到了這里,往回看能找到能找到兩個(gè)地方調(diào)用的是同一個(gè)函數(shù),估計(jì)是對(duì)加密結(jié)果進(jìn)行比較:
從第一次比較分析,先把用來(lái)比較的數(shù)據(jù)dump下來(lái):
enc1 = b"/x88/xE7/x03/xB4/x36/xCD/x97/xAB/x5A/xA5/xA6/x0B/xDF/xCE/x08/x3B/x9D/x90/x32/x3C/x4E/x15/x14/xBD/x8D/x38/x38/xB0/xEE/x2A/xBC/x4B/xF9/xAA/x24/x26/x76/xA3/xA5/x75/x5E"
從比較函數(shù)往前找,找到了這個(gè)很詭異的地方:
?百度搜索關(guān)鍵詞expand 32-byte k找到了GitHub上的一處代碼:
一比對(duì)發(fā)現(xiàn)是幾乎一模一樣(實(shí)際上并不一樣),鎖定第一個(gè)加密算法是ChaCha20:
順藤摸瓜找到密鑰:
然而用了各種Python庫(kù)和在線網(wǎng)站都解密不了,一度懷疑人生...
后來(lái)分析發(fā)現(xiàn)了題目里用到的ChaCha20算法貌似跟正常的ChaCha20算法不太一樣,一般來(lái)說(shuō)ChaCha20算法輸入的Nonce(隨機(jī)數(shù))是8字節(jié),題目中的ChaCha20算法卻給了12個(gè)字節(jié)的Nonce,于是改變思路去GitHub上翻了幾個(gè)ChaCha20的C語(yǔ)言實(shí)現(xiàn),找到了題目用到的源碼:
比對(duì)下來(lái)發(fā)現(xiàn)是完全一樣,依葫蘆畫瓢寫出exp的第一部分:
#include "chacha20.h"#include #include int main(){ char enc[100] = "/x88/xE7/x03/xB4/x36/xCD/x97/xAB/x5A/xA5/xA6/x0B/xDF/xCE/x08/x3B/x9D/x90/x32/x3C/x4E/x15/x14/xBD/x8D/x38/x38/xB0/xEE/x2A/xBC/x4B/xF9/xAA/x24/x26/x76/xA3/xA5/x75/x5E"; char key[100] = "tzgkwukglbslrmfjsrwimtwyyrkejqzo"; char nonce[100] = "oaeqjfhclrqk"; struct chacha20_context *ctx = (struct chacha20_context*)malloc(sizeof(struct chacha20_context)); chacha20_init_context(ctx,(uint8_t*)key,(uint8_t*)nonce,0x80); chacha20_xor(ctx,(uint8_t*)enc,41); printf(enc);}
flag{have_you_tried_ghidra9.2_decompiler_
其實(shí)更好的方法是直接動(dòng)態(tài)調(diào)試dump密鑰流異或,無(wú)奈riscv的動(dòng)態(tài)調(diào)試環(huán)境沒搭起來(lái)。
然而這種ChaCha20實(shí)現(xiàn)到底是變體還是翻車就不知道了...
第二部分則是一個(gè)很明顯的TEA:
寫出第二部分的exp:
from pytea import TEA key = b"/xBB/xA0/x68/x13/x1E/xCE/x0A/x19/x57/xA3/xD8/x35/x61/x2C/xBF/x26"enc = b"/xF9/x87/x50/xC4/xB2/xF2/x03/x07/x3C/xF4/x74/x69/x59/xBB/xB4/xED/x2A/xB0/xF0/x0F/xF2/x20/x85/x00/xDD/x23/xCD/xFD/x75/x48/x02/x35/xD3/xB6/xD7/xF1/xE1/x1B/xF2/x74/x12/xBF/x2D/xCB/xF6/x53/xB4/xA4"cipher = TEA(key)print(cipher.Decrypt(enc,16).decode())
if_you_have_hexriscv_plz_share_it_with_me_thx:P}
完整的flag:
flag{have_you_tried_ghidra9.2_decompiler_if_you_have_hexriscv_plz_share_it_with_me_thx:P}
最后再總結(jié)一下識(shí)別單向散列算法和對(duì)稱加密算法的方法:
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/119551.html
摘要:非對(duì)稱加密算法的安全性往往需要基于數(shù)學(xué)問(wèn)題來(lái)保障,目前主要有基于大數(shù)質(zhì)因子分解離散對(duì)數(shù)橢圓曲線等經(jīng)典數(shù)學(xué)難題進(jìn)行保護(hù)。消息認(rèn)證碼基于對(duì)稱加密,可以用于對(duì)消息完整性進(jìn)行保護(hù)。 Hash 算法與數(shù)字摘要 Hash (哈希或散列)算法它能將任意長(zhǎng)度的二進(jìn)制明文串映射為較短的(通常是固定長(zhǎng)度的)二進(jìn)制串(Hash值),并且不同的明文很難映射為相同的Hash值。 Hash 定義 Hash (哈希...
摘要:接下來(lái),作者從密碼算法的誤用著手,針對(duì)一些常量,改進(jìn)了靜態(tài)分析工具。具體來(lái)說(shuō),就是在的基礎(chǔ)上做了動(dòng)態(tài)分析方法和靜態(tài)分析方法相結(jié)合的策略,在線記錄文件,離線檢測(cè)分析,使得整個(gè)工具更加完善。 ...
摘要:還有很多開發(fā)者沒有意識(shí)到的加密算法的問(wèn)題。不要使用哈希函數(shù)做為對(duì)稱加密算法的簽名。開發(fā)者建議使用基于口令的加密算法時(shí),生成密鑰時(shí)要加鹽,鹽的取值最好來(lái)自,并指定迭代次數(shù)。不要使用沒有消息認(rèn)證的加密算法加密消息,無(wú)法防重放。 本文作者:阿里移動(dòng)安全@伊樵,@舟海 Android開發(fā)中,難免會(huì)遇到需要加解密一些數(shù)據(jù)內(nèi)容存到本地文件、或者通過(guò)網(wǎng)絡(luò)傳輸?shù)狡渌?wù)器和設(shè)備的問(wèn)題,但并不是使用了加...
閱讀 3013·2021-11-16 11:42
閱讀 3651·2021-09-08 09:36
閱讀 949·2019-08-30 12:52
閱讀 2481·2019-08-29 14:12
閱讀 769·2019-08-29 13:53
閱讀 3583·2019-08-29 12:16
閱讀 644·2019-08-29 12:12
閱讀 2468·2019-08-29 11:16