前言
最近寫個(gè)東西玩玩玻侥,需要用到MD5,找了半天亿蒸,發(fā)現(xiàn)MS的MD5連個(gè)接口都沒有凑兰。當(dāng)然事后goolge baidu還是找到了掌桩,可能用得小。openssl也可以票摇,不過為了這些小功能去找個(gè)瑞士軍刀代碼,也是無聊(笑)砚蓬。
正文
其實(shí)MS是有這個(gè)接口矢门,不過沒有暴露出來,在ntdll中導(dǎo)出函數(shù)能找到灰蛙。當(dāng)然是不知到形參之類的祟剔,怎么辦? 只能找標(biāo)準(zhǔn)摩梧,rfc1321是MD5 的標(biāo)準(zhǔn)物延,里面有個(gè)MD5的實(shí)現(xiàn)。大概如下:
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init PROTO_LIST ((MD5_CTX *));
void MD5Update PROTO_LIST
((MD5_CTX *, unsigned char *, unsigned int));
void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
當(dāng)然仅父,對(duì)于巨硬大佬不跟標(biāo)準(zhǔn)早有所聞叛薯,我是不相信這么簡(jiǎn)單的。事實(shí)上笙纤,照上面的代碼來耗溜,反匯編跟進(jìn)MD5Init時(shí),你可以發(fā)現(xiàn)state與count的位置剛好倒轉(zhuǎn)省容。只好繼續(xù)google(笑)抖拴,后來找到個(gè)軟件 Process hacker 的 doc,有個(gè)詳細(xì)的MD5_CTX的結(jié)構(gòu)腥椒,試了下還真能用阿宅,代碼風(fēng)格跟巨硬一個(gè)樣。
typedef struct MD5state_st
{
ULONG i[2];
ULONG buf[4];
UCHAR in[64];
UCHAR digest[16];
} MD5_CTX;
其中笼蛛,digest是MD5緩存洒放,最后輸出的地方,所以MD5Final只接受單個(gè)參數(shù)滨砍。最后大概就是這樣:
#include <windows.h>
#include <tchar.h>
#pragma pack(push,1)
typedef struct MD5state_st
{
ULONG i[2];
ULONG buf[4];
UCHAR in[64];
UCHAR digest[16];
} MD5_CTX;
#pragma pack(pop)
typedef void (__stdcall *PMD5Init)(MD5_CTX *);
typedef void (__stdcall *PMD5Update)(MD5_CTX *, void*, ULONG);
typedef void (__stdcall *PMD5Final)( MD5_CTX *);
__declspec(dllexport)
void __stdcall MD5Init(MD5_CTX *c) {
HMODULE ntdll = GetModuleHandle(_T("ntdll.dll"));
if (!ntdll)return;
PMD5Init ntdll_MD5_Init = (PMD5Init)GetProcAddress(ntdll, "MD5Init");
ntdll_MD5_Init(c);
}
__declspec(dllexport)
void __stdcall MD5Update(MD5_CTX *c, void * data, ULONG len) {
HMODULE ntdll = GetModuleHandle(_T("ntdll.dll"));
if (!ntdll)return;
PMD5Update ntdll_MD5_Update = (PMD5Update)GetProcAddress(ntdll, "MD5Update");
ntdll_MD5_Update(c, data,len);
}
__declspec(dllexport)
void __stdcall MD5Final( MD5_CTX *c) {
HMODULE ntdll = GetModuleHandle(_T("ntdll.dll"));
if (!ntdll)return;
PMD5Final ntdll_MD5_Final = (PMD5Final)GetProcAddress(ntdll, "MD5Final");
ntdll_MD5_Final(c);
}
這里不用LoadLibrary拉馋,因?yàn)槊總€(gè)進(jìn)程都會(huì)加載ntdll,所以直接GetModuleHandle就可以惨好。__stdcall標(biāo)準(zhǔn)call煌茴,巨硬親兒子,dll一般都是用這個(gè)調(diào)用約定日川,也可以反匯編跟進(jìn)函數(shù)蔓腐,看看是不是函數(shù)自己清棧,不明白可以查下調(diào)用約定龄句,相互調(diào)用的知識(shí)點(diǎn)回论。
結(jié)尾
最后散罕,免不了放個(gè) Window MD5 的github,順便介紹下 “巨硬的加密function Cryptography Reference” 和 “Process hacker 的doc”傀蓉,挺有用的東西欧漱。
編輯于 【2018.3.9】