DLL文件在CANoe的使用方法
DLL文件在診斷里面可以用在0x27秘鑰服務里面,對解密有幫助,在下圖位置加載。
DLL文件制作
vector公司本來就給了我們一個demo,先拷貝一份下來,別把原來的文件給改壞了。我這個是CANoe12,demo代碼的路徑在C:\Users\Public\Documents\Vector\CANoe\Sample Configurations 12.0.75\CAN\Diagnostics\UDSSystem\SecurityAccess\Sources,大家可以參考下,把里面這個KeyGenDll_GenerateKeyEx文件夾復制一份出來,當然你也可以用KeyGenDll_GenerateKeyExOpt,待會打開源代碼看得到是差不多的。
打開Visual Studio 2019,將工程里面的工程文件GenerateKeyExImpl.vcproj拖進去,就能打開工程。展開工程,然后打開源文件GenerateKeyExImpl.cpp。
程序比較簡單,還有注釋,里面有很多空行,我刪了幾行放在這里大家看看,這個是工程KeyGenDll_GenerateKeyEx的源代碼。
// KeyGeneration.cpp : Defines the entry point for the DLL application.
#include <windows.h>
#include "KeyGenAlgoInterfaceEx.h"BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{return TRUE;
}KEYGENALGO_API VKeyGenResultEx GenerateKeyEx(const unsigned char* iSeedArray, /* Array for the seed [in] */unsigned int iSeedArraySize, /* Length of the array for the seed [in] */const unsigned int iSecurityLevel, /* Security level [in] */const char* iVariant, /* Name of the active variant [in] */unsigned char* ioKeyArray, /* Array for the key [in, out] */unsigned int iKeyArraySize, /* Maximum length of the array for the key [in] */unsigned int& oSize /* Length of the key [out] */)
{if (iSeedArraySize>iKeyArraySize)return KGRE_BufferToSmall;for (unsigned int i=0;i<iSeedArraySize;i++)ioKeyArray[i]=~iSeedArray[i];oSize=iSeedArraySize;return KGRE_Ok;
}
這個是KeyGenDll_GenerateKeyExOpt工程的源代碼GenerateKeyExOpt.cpp,相對于KeyGenDll_GenerateKeyEx工程就是多了個選項作為入參,高級用法才會用到,我們一般都用不到,所以這里就用KeyGenDll_GenerateKeyEx工程。
//
/// Seed & Key DLL with extended interface and options argument
/// This is an example implementation for CANoe demo configuration "UDSsim"
//#include <windows.h>
#include "GenerateKeyExOpt.h"KEYGENALGO_API VKeyGenResultExOpt GenerateKeyExOpt(const unsigned char* ipSeedArray, // Array for the seed [in]unsigned int iSeedArraySize, // Length of the array for the seed [in]const unsigned int iSecurityLevel, // Security level [in]const char* ipVariant, // Name of the active variant [in]const char* ipOptions, // Optional parameter which might be used for OEM specific information [in]unsigned char* iopKeyArray, // Array for the key [in, out]unsigned int iMaxKeyArraySize, // Maximum length of the array for the key [in]unsigned int& oActualKeyArraySize) // Length of the key [out]
{// Check the input argumentsif( iSecurityLevel == 0 || iSecurityLevel > 10)return KGREO_SecurityLevelInvalid;if( iMaxKeyArraySize < iSeedArraySize || 4 > iSeedArraySize)return KGREO_BufferToSmall;if( !ipSeedArray || !iopKeyArray || !ipOptions || strlen( ipOptions) < iSeedArraySize)return KGREO_UnspecifiedError;// Copy the input bytes to the output bytesmemcpy( iopKeyArray, ipSeedArray, iSeedArraySize);// As an example each byte in the options array will be added to each byte of the seed array securityLevel times.for( unsigned int l = 0; l < iSecurityLevel; ++l){for( unsigned int i = 0; i < iSeedArraySize; ++i)iopKeyArray[i] += ipOptions[i];}oActualKeyArraySize = iSeedArraySize;return KGREO_Ok;
}
修改KeyGenDll_GenerateKeyEx工程源代碼GenerateKeyExImpl.cpp,里面做了注釋。
KEYGENALGO_API VKeyGenResultEx GenerateKeyEx(unsigned char* iSeedArray, /* 種子數組 */unsigned int iSeedArraySize, /* 種子長度 */const unsigned int iSecurityLevel, /* 秘鑰等級(調試打印) */const char* iVariant, /* 激活狀態(調試打印) */unsigned char* ioKeyArray, /* 秘鑰數組 */unsigned int iKeyArraySize, /* 秘鑰長度 */unsigned int& oSize /* 秘鑰長度(調試打印) */)
{if (iSeedArraySize>iKeyArraySize)//秘鑰長度大于種子長度的話就是長度錯誤return KGRE_BufferToSmall;……(這里是我的算法,計算出來的秘鑰放在iSeedArray[]數組)for (int i = 0; i < iKeyArraySize; i++) {ioKeyArray[i] = iSeedArray[i];}oSize = iSeedArraySize;//這個其實沒啥用,長度是CDD里面定義的return KGRE_Ok;
}
對著工程右鍵,重新生成就行,輸出信息會告訴你把DLL文件生成到了哪里。
DLL文件檢查
如果你很有自信一次寫對,那直接在CANoe里面直接加載就行。如果想謹慎點,想要檢查寫得對不對,就新建個控制臺工程來調用DLL文件里面的函數進行驗證。
把上面生成的DLL文件拷貝到控制臺路徑下。
調用代碼如下
// CallDLL.cpp : 此文件包含 "main" 函數。程序執行將在此處開始并結束。
//
#include <iostream>
#include <Windows.h>
#include <tchar.h>using namespace std;
#define iSeedArraySize 16
const unsigned char SeedArray[iSeedArraySize] = {0xD1,0x28,0xD2,0x7B,0x25,0xCE,0x78,0x22,0xCB,0x75,0x1E,0xC8,0x71,0x1B,0xC5,0x6E }; const unsigned int iSecurityLevel = 1;
const char iVariant = 0;#define iKeyArraySize 16
unsigned char ioKeyArray[iSeedArraySize] = { 0x0 };unsigned int oSize = 0;int main()
{HINSTANCE handle = LoadLibrary(_T("SeednKey.dll"));//加載dll ,需要加上頭文件tchar.h并在調用時加上_T 由句柄指向dll文件cout << "Dll Adddr:" << handle << endl;if (handle){typedef int(*GenerateKeyExOpt_API_Type)(const unsigned char*,unsigned int,const unsigned int,const char*,unsigned char*,unsigned int,unsigned int &);GenerateKeyExOpt_API_Type GenerateKeyExOpt_API_Point = (GenerateKeyExOpt_API_Type)GetProcAddress(handle, "GenerateKeyEx"); //GetProcAddress獲取dll中的Add_Func函數,用add_API_Point指向函數它cout << "dll 函數的句柄返回值:" << GenerateKeyExOpt_API_Point << endl;//打印dll的函數句柄地址值,不為0就說明調用成功printf("\n");if (GenerateKeyExOpt_API_Point){int result = (*GenerateKeyExOpt_API_Point)(SeedArray,iSeedArraySize, iSecurityLevel,&iVariant, ioKeyArray, iKeyArraySize, oSize);for (int i = 0; i < iSeedArraySize; i++) {/*打印種子*/printf("SeedArray[%d]: %2X\n", i, SeedArray[i]);}printf("\n");for (int j = 0; j < iKeyArraySize; j++) {/*打印秘鑰*/printf("ioKeyArray[%d]: %2X\n", j, ioKeyArray[j]);}cout << "oSize = " << oSize << endl;/*調試打印*/FreeLibrary(handle); //釋放句柄}}return 0;
}// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
// Debug program: F5 or Debug > Start Debugging menu
對一下打印出來的結果,是對的話就是驗證通過。
CDD文件配置
0x27服務的長度是在CDD文件里面配置的,單純改代碼是改不動的。
用CANdelaStudio打開CDD文件,勾選這個,把0x27服務帶出來。
長度,解密等級都在這里設置。
DLL文件使用
按照本文最上面的使用方法加載進去,雙擊能發送。