原文防盗链地址:http://www.cnblogs.com/aj3423/p/3477042.html
xuetr 介绍:http://www.epoolsoft.com/forum.php?mod=viewthread&tid=18&extra=page%3D1
xuetr pro 下载地址:http://down.epoolsoft.com/pchunter/PCHunter_pro.zip
key file 下载: http://files.cnblogs.com/aj3423/pchunter.ek.rar
pro版 介绍上说会读取 pchunter.ek 这个keyfile,所以od载入,bp CreateFileA, bp CreateFileW
会断两次,都是断在同一个函数,稍微跟几步会检查文件大小是不是256字节,不是就over,
打开 pchunter.ek,我开始是填入 12345678901234 ... 123456 共256字节, 填什么都行,后来发觉填写 00~FF更方便定位(下面代码就是这样)
往下走,来到算法部分,首先是
3个参数的函数 (??, "ShouJiErShiSiShi", 16), 预测是给算法准备key,因为好多算法都是这样,先set_key,然后再调用encrypt/decrypt,
紧接着下一行
4个参数的函数 (??, output buffer, key_file内容, 128), 一看就是解密keyfile了,到这还不知道是什么算法,猜测出aes_decrypt有几点:
1. 第一个图的 aes_set_key 里,用 ida 分析 41FB90,可以看到有 switch( case 16: ... case 24: ... case 32: ), aes中 16,24,32 分别对应密钥长度是 128, 192, 256 bit,调试时的值是 16, 和上面的key "ShouJiErShiSiShi" 长度是 16 对应
2. 算法有个特征是异或 0x1B,往上搜了下,aes 中有用到
3. 输入和输出有固定模式,因为输入是1234567890..这样,所以图上5行是一个循环, 而输出也是5行一个循环,
aes的ecb模式就是,google下可以搜到:
4. 作者肯定是自己encrypt,然后在程序里在decrypt
简单写了个测试,确认是 aes_ecb_decrypt,接着往下
来到一堆获取时间的函数,但确定不了 是从128字节的哪部分读取的,所以重新填充key file,这次用 00 ~ FF 填充, 发觉是从偏移 80 和 88 分别读取了两个 FILETIME 结构体,作为starttime 和 endtime
最后,写段代码生成 keyfile:
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
|
#include <windows.h>
#include <string>
#include <iostream>
#include <fstream>
using
namespace
std;
#include "crypto/aes.h" // 用到了cryptopp 库
#include "crypto/modes.h"
#include "crypto/filters.h"
using
namespace
CryptoPP;
template
<
class
ByteT>
string hex2str(ByteT* hex,
int
len,
const
string& delim=
" "
) {
if
(len == 0)
return
""
;
string s;
char
x[4];
for
(
int
i=0; i<len; i++) {
sprintf_s(x, 4,
"%02X"
, ((unsigned
char
*)hex)[i]);
s += x;
if
(i != len-1) s += delim;
// append delim if not the last char
}
return
s;
}
string hex2str(
const
string& hex,
const
string& delim=
" "
) {
return
hex2str(hex.c_str(), hex.length(), delim);
}
string aes_encrypt(string& plain, string& key) {
ECB_Mode< AES >::Encryption e((byte*)key.c_str(), key.length());
string cipher;
StringSource ss(plain,
true
,
new
StreamTransformationFilter( e,
new
StringSink( cipher ),
StreamTransformationFilter::NO_PADDING) );
return
cipher;
}
#pragma pack(push, 1)
struct
reg {
byte unknown_1[80];
FILETIME ft_beg;
FILETIME ft_end;
byte unknown[32];
};
#pragma pack(pop)
int
main() {
string key =
"ShouJiErShiSiShi"
;
reg r;
byte* p = (byte*)&r;
for
(unsigned
int
i=0; i<
sizeof
(reg); i++) {
// 填充 00 ~ FF
p[i] = i;
}
SYSTEMTIME st;
GetSystemTime(&st);
// 得到当前时间 -> start time
SYSTEMTIME st_new = st;
st_new.wYear += 10;
// 当前时间+10年 -> end time
SystemTimeToFileTime(&st, &r.ft_beg);
// 转成8字节的 FILETIME,xuetr用的这个
SystemTimeToFileTime(&st_new, &r.ft_end);
string plain;
plain.assign((
const
char
*)&r,
sizeof
(r));
cout <<
"raw:"
<< endl << hex2str(plain) << endl;
string encrypted = aes_encrypt(plain, key);
// 加密
// cout << "encrypted:" << endl << hex2str(encrypted) << endl;
ofstream ofs(
"e:/pchunter.ek"
, ios::binary);
// 写到 key file
ofs << hex2str(encrypted,
""
);
ofs.close();
}
|
128 字节的 keyfile,里面只用到了16字节的两个 FILETIME 时间? 还是我漏了什么?