【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】

上一篇下一篇

猜你喜欢

热点阅读