【Microsoft】Windows Md5 消息摘要功能
2018-03-09 本文已影响0人
Kernel32
前言
最近写个东西玩玩,需要用到MD5,找了半天,发现MS的MD5连个接口都没有。当然事后goolge baidu还是找到了,可能用得小。openssl也可以,不过为了这些小功能去找个瑞士军刀代码,也是无聊(笑)。
正文
图像 1.png其实MS是有这个接口,不过没有暴露出来,在ntdll中导出函数能找到。当然是不知到形参之类的,怎么办? 只能找标准,rfc1321是MD5 的标准,里面有个MD5的实现。大概如下:
/* 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 *));
当然,对于巨硬大佬不跟标准早有所闻,我是不相信这么简单的。事实上,照上面的代码来,反汇编跟进MD5Init时,你可以发现state与count的位置刚好倒转。只好继续google(笑),后来找到个软件 Process hacker 的 doc,有个详细的MD5_CTX的结构,试了下还真能用,代码风格跟巨硬一个样。
typedef struct MD5state_st
{
ULONG i[2];
ULONG buf[4];
UCHAR in[64];
UCHAR digest[16];
} MD5_CTX;
其中,digest是MD5缓存,最后输出的地方,所以MD5Final只接受单个参数。最后大概就是这样:
#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,因为每个进程都会加载ntdll,所以直接GetModuleHandle就可以。__stdcall标准call,巨硬亲儿子,dll一般都是用这个调用约定,也可以反汇编跟进函数,看看是不是函数自己清栈,不明白可以查下调用约定,相互调用的知识点。
结尾
最后,免不了放个 Window MD5 的github,顺便介绍下 “巨硬的加密function Cryptography Reference” 和 “Process hacker 的doc”,挺有用的东西。
编辑于 【2018.3.9】