功能代码:
int get_PE_feature_rof(string path_r,int codeArr[],int codeCtrl[],int len){
// 打开文件
ifstream in = ifstream(path_r, ios::binary);
if (!in.is_open()){
cout << "文件打开失败:" << GetLastError() << endl;
in.close();
return 0;
}
// 获取文件大小、文件名
long long Beg = in.tellg();
in.seekg(0, ios::end);
long long End = in.tellg();
long long fileSize = End - Beg;
in.seekg(0, ios::beg);
// 读文件(每次循环读取 1 字节)
int byteBeenRead = 0; // 已经读取的字节数
unsigned char temp; // 存放读取内容的缓冲区
int rof_feature = 0; // 特征 ROF
int codeArrSub = 0; // 要对比的 codeArr[] 下标
BOOL isFound = FALSE; // 是否找到特征
int cmpAllReady = 0; // 已经对比特征的次数
while (in.read((char*)&temp, 1)/* && isFound == FALSE*/){
byteBeenRead++;
// 读 1 字节
int hex = (unsigned)temp;
// 控制码为0 则比较下一个
if(codeCtrl[codeArrSub] == 0){
codeArrSub++;
// 是否比较完毕
if(codeArrSub == len){
cout << "find rof" << endl;
rof_feature = byteBeenRead - len;
isFound = TRUE;
break;
}
continue;
}
// 匹配到一个特征
if(hex == codeArr[codeArrSub]){
codeArrSub++;
// 是否比较完毕
if(codeArrSub == len){
cout << "find rof" << endl;
rof_feature = byteBeenRead - len;
isFound = TRUE;
break;
}
continue;
}
// 匹配失败
else{
codeArrSub=0;
continue;
}
}
//cout << "rof_feature = " << hex << rof_feature << endl;
in.close();
return rof_feature;
}
调用例子
int codeArr_lea_win7[] = {
0x48,0x8d,0x0d,0x37,0x41,0xdc,0xff,
0x45,0x33,0xc0,
0x48,0x8b,0xd7,
0x48,0x8d,0x0c,0xd9,
0xe8,0x98,0x54,0xf7,0xff,
0x84,0xc0,
0x75,0x11,
0xff,0xc3,
0x83,0xfb,0x40,
0x72,0xdf,
0x48,0x8b,0xcf,
0xe8,0x65,0xd8,0xf7,0xff,
0xeb,0xcc
};
int codeCtrl_lea_win7[] = {
1,1,1,0,0,0,0,
1,1,1,
1,1,1,
1,1,1,1,
1,0,0,0,0,
1,1,
1,1,
1,1,
1,1,1,
1,1,
1,1,1,
1,0,0,0,0,
1,1
};
int rof_lea = get_PE_feature_rof("C:\\Windows\\SysNative\\ntoskrnl.exe",codeArr_lea_win7,codeCtrl_lea_win7,43);
延申,根据 rof 计算 vaof 假设我们已经拿到了 ROF = 0x3d3f60 观察区段表:
0x46ec00 所以处于 PAGE 区段 根据公式 vaof = 我们的rof - 所属区段rof + 所属区段va
在这里也就是:
vaof = 0x3d3f60 - 0x235000 + 0x2be000;
拿到 vaof 后,再加上驱动基地址就能得到对应未公开 API 再内核中的内存地址