国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

逆向中常見的Hash算法和對(duì)稱加密算法的分析

hedzr / 3650人閱讀

摘要:逆向中常常出現(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í)別方法。

0xFF. 前言

在很長(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章的隨書附帶文件和各大比賽中的題目。

0x00. 目錄

單向散列算法:

  1. MD5
  2. SHA

對(duì)稱加密算法:

  1. RC4
  2. TEA
  3. DES
  4. AES
  5. SM4
  6. ChaCha20

0X01. MD5

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)分析的方法。

0x02. SHA

安全散列算法(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)

0x03. RC4

RC4是一種比較簡(jiǎn)單的流密碼,該算法雖然沒有用到特征常量,但是特征也比較容易識(shí)別。

分析RC4 Sample.exe文件。
還是通過(guò)導(dǎo)入表找到關(guān)鍵代碼:

?sub_401000函數(shù)明顯具有RC4密鑰調(diào)度算法(KSA)的特征:

sub_401070函數(shù)是RC4算法的第二步:

0x04. TEA

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

0x05. DES

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

圖一中的IPFP分別代表初始置換(Initial Permutation)和末尾置換(Final Permutation),圖二中的S1S8是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算法:

0x06. AES

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()}")

0x07. SM4

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!

0x08. ChaCha20

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}

0x09. 總結(jié)

最后再總結(jié)一下識(shí)別單向散列算法和對(duì)稱加密算法的方法:

  1. 直接用IDA的插件Findcrpyt
  2. RC4、TEA這些流程比較簡(jiǎn)單的算法可以直接通過(guò)加密過(guò)程識(shí)別
  3. 一些用到了常量的算法,可以通過(guò)它的特征常量識(shí)別。比如TEA的delta、ChaCha20的sigma、DES和AES以及SM4的S-Box等等
  4. 善用GitHub,作為老程序員,這種復(fù)雜的加密算法一般都是在GitHub上抄的(至少我不會(huì)自己寫hh)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/119551.html

相關(guān)文章

  • 區(qū)塊鏈學(xué)習(xí)之密碼學(xué)安全技術(shù)(五)

    摘要:非對(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 (哈希...

    aboutU 評(píng)論0 收藏0
  • 檢測(cè)工具進(jìn)階——結(jié)合靜態(tài)分析動(dòng)態(tài)分析工具論文分享

    摘要:接下來(lái),作者從密碼算法的誤用著手,針對(duì)一些常量,改進(jìn)了靜態(tài)分析工具。具體來(lái)說(shuō),就是在的基礎(chǔ)上做了動(dòng)態(tài)分析方法和靜態(tài)分析方法相結(jié)合的策略,在線記錄文件,離線檢測(cè)分析,使得整個(gè)工具更加完善。 ...

    canger 評(píng)論0 收藏0
  • Android 應(yīng)用安全開發(fā)之淺談加密算法

    摘要:還有很多開發(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)題,但并不是使用了加...

    不知名網(wǎng)友 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

hedzr

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<