MD5加密算法逆向

MD5加密算法逆向

Serendy Magician

基本的IDA Pro(Slides)

MD5加密原理

首先你得会基本的MD5加密算法原理,给一个传送门

MD5哈希函数加密算法原理

也可以看PPT P59-P65

什么方法可以快速确定是MD5

看提示–>找字符串–>找判断

如何真正确定是MD5

需要对比较程序的函数功能进行解读,对加密函数的每个子函数的功能都分析清楚,最终确定是MD5哈希加密算法

BTW:MD5只能使用碰撞解密,所以判断出是MD5了之后我们就需要进行碰撞脚本的编写了

逆向的基本思路

找目标散列值–>找到原文和长度–>找到原文的字典集合(–>破解的速度)–>写碰撞程序(Python)

然后这个题目有一个比较坑的点就是他的字符串长度是4字节+而不是4字节

逆向步骤分析

见PPT第7-9讲 P68-77

最终完成的碰撞程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# -*- coding: utf-8 -*-
from hashlib import md5
from string import digits, ascii_letters, ascii_lowercase, ascii_uppercase, punctuation, whitespace, printable
from itertools import permutations, product
import sys

def decipher_md5(md5_value: str, plaintext_len: int = 4, \
plaintext_letter_dict: str = ascii_letters+punctuation, dup: bool =False):

md5_value = md5_value.lower()
if len(md5_value) != 32:
print('\n不是有效的md5散列!')
sys.exit(-1)

try:
if dup: # 全排列,可重复
plaintext_set = [''.join(p) for p in product(punctuation, repeat=plaintext_len)]
else: # 全排列,不可重复
plaintext_set = permutations(plaintext_letter_dict, plaintext_len)

for item in plaintext_set:
item=''.join(item)
# print(item)

if md5(item.encode()).hexdigest() == md5_value:
print('\n成功解出明文: ' + md5_value + ' ==> ' + item)
break

if md5(item.encode()).hexdigest() != md5_value:
sys.exit(1)

except SystemExit:
print('\n解析失败,请检查下给定的明文长度(默认 plaintext_len: int = 4)!!!')

def test():
decipher_md5(md5_value = 'b5a5d6911aa48b50139c7122ef05ca9a', plaintext_letter_dict = punctuation, dup=True)

if __name__ == '__main__':
# test()
decipher_md5(md5_value = '23d4a52c56357cb705137656744dc055', plaintext_letter_dict = ascii_letters)

加密函数复用(DLL注入)——动态分析

①MD5计算 复用MD5加密程序

动态调试,复用MD5程序

找到计算MD5函数(操作复杂)

②怎么复用?

③直接ASM太复杂

④DLL注入

找到散列+MD5函数指针

传3个指针:散列值 原文长度 MD5函数指针

注入程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include "main.h"
#include <stdio.h>
#include <math.h>
#include <string.h>

void DLL_EXPORT randomCHR(int flag_len)
{
unsigned char i, j;
unsigned int temp = cnt_no;

for(i=0; i<flag_len; i++)
flag[i] = letters[0];

for (i = 0; temp != 0; i++) {
j = temp % strlen(letters);
temp = temp / strlen(letters);

flag[i] = letters[j];
}
flag[flag_len] = '\0'; // 强制截断

cnt_no ++;
}

void DLL_EXPORT crack(char * target_hash, int flag_len, void(*hash_func)(char *, char *, unsigned int))
{
unsigned char i, j;
unsigned int temp;
char out[100];

for(cnt_no=0; cnt_no<pow(26, flag_len); cnt_no++) {
temp = cnt_no;

for(i=0; i<flag_len; i++)
flag[i] = letters[0];

for (i = 0; temp != 0; i++)
{
j = temp % strlen(letters);
temp = temp / strlen(letters);

flag[i] = letters[j];
}
flag[flag_len] = '\0';

hash_func(out, flag, flag_len);
if ( !strncmp(out, target_hash, strlen(target_hash)) )
MessageBoxA(0, flag, "已成功匹配", MB_OK | MB_ICONINFORMATION);
}
}

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// attach to process
// return FALSE to fail DLL load
char addr_info[100];
sprintf(addr_info, "randomCHR: \t0x%p,\tcrack: \t0x%p\n&cnt_no: \t0x%p,\tflag: \t0x%p", randomCHR, crack, &cnt_no, flag);

MessageBoxA(0, addr_info, "地址信息", MB_OK | MB_ICONINFORMATION);

break;

case DLL_PROCESS_DETACH:
// detach from process
break;

case DLL_THREAD_ATTACH:
// attach to thread
break;

case DLL_THREAD_DETACH:
// detach from thread
break;
}
return TRUE; // succesful
}

⑤调用Crack进行破解

⑥进行二进制编辑

操作步骤

IDA Pro找到MD5地址:401719(也就是说还是得分析出MD5函数)

在x32dbg中ctrl+G定位到地址401719

按下空格看到MD5函数的地址,并记录

在401716处下断点,运行至此处,准备开始二进制编辑

加载注入程序,使用ScyllaHide插件,Inject DLL

注入成功之后插件会提示函数注入地址:

读出crack函数入口地址(每次加载时都不太一样):6a1556

按下空格修改汇编指令:

将[esp]改为[esp+0x08],输入0x4016a1,传入第三个参数:散列值

将[esp]改为[esp+0x04],输入0x04,传入第二个参数:原文长度

在[esp]处,根据x32dbg提示的地址,输入0x0040508c,传入第三个参数:MD5函数指针

将下一步的call的地址改成注入函数入口地址(0x006a1556)

(点击右侧的EIP可以直接返回)

下两个断点:

然后就可以解出明文:BUPT

Plus:如何编写DLL文件

使用Codeblocks,在创建项目中选择Dynamic Link Library

问题解释

在进行DLL注入的时候如果在断点注入可能会出现卡死的现象,此时注入就失败了

解决方案:不应该在401716处进行注入,应该在程序的Entrypoint处进行注入,并且要在程序已经出现了提示信息“Please input your flag:”之后再进行注入,否则也会卡死

  • Title: MD5加密算法逆向
  • Author: Serendy
  • Created at : 2023-04-21 17:20:57
  • Updated at : 2023-07-12 11:27:52
  • Link: https://mapleqian.github.io/2023/04/21/MD5加密算法逆向/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments