? 相关文章
-
?CANoe DLL编程(一)—— Visual Studio 创建DLL以及动态调用
-
?CANoe DLL编程(二)—— 创建CANoe适用的DLL以及调用
-
?CANoe DLL编程(三)——DLL和回调函数
-
?CANoe DLL编程(四)——SendKey DLL的CANoe应用
-
?CANoe DLL编程(五)——通过VS 生成 SendKey.dll
-
?本章节内容演示源码下载,点击跳转?
?前言
相关文章
-
实际工程中,会产生这种情况,OEM给了你seedkey.dll ,没有给你具体算法,因为它不希望自己密钥泄露,作为供应商,还有自己的sub function,这个时候,我们就需要在OEM提供的DLL基础上,再封装一层。
-
这里博主强烈建议你先阅读 ?CANoe DLL编程(五)——通过VS 生成 SendKey.dll内容基于它扩展开来的
-
软件环境:
win10 x64
visual studio 2019
CANoe 11 x64
文章目录
- ? 相关文章
- ?前言
- 相关文章
- ? DLL二次封装代码解读
- ? 二次封装后的DLL测试
- ?总结
? DLL二次封装代码解读
1?? 这里假设我们之前生成的DLL SeednKey_Opt_More.dll
是客户给的,seedkey 的算法是保密的,只有level1和level 11,现在我们要把自己的level 13加进去`
- 我们把
KeyGenDll_GenerateKeyEx - Copy
拷贝一份KeyGenDll_GenerateKeyEx_Level_13
2?? 我们完善KeyGenDll_GenerateKeyEx_Level_13
工程中的代码,然后重新rebuild
。
-
我原来实际工程可以直接
LoadLibrary(_T(“SeednKey_Opt_More.dll”))
就可以了,这里不知道为什么不行了,必须用绝对路径才行 -
就两个函数
GenerateKeyExOpt
,CANoe API的接口,和原来一样;GenerateKeyExOpt_new
我自己新定义的,用来封装DLL
// KeyGeneration.cpp : Defines the entry point for the DLL application.
//#include <windows.h>
#define KEYGENALGO_EXPORTS
#include "KeyGenAlgoInterfaceEx.h"
#include <tchar.h>
#include <iostream>BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
return TRUE;
}int GenerateKeyExOpt_new(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* iVariant, /* Name of the active variant [in] */const char* ipOptions,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] */
)
{
HINSTANCE handle = LoadLibrary(_T("C:\\Users\\Public\\Documents\\Vector\\CANoe\\Sample Configurations 11.0.55\\CAN\\Diagnostics\\UDSSystem\\SecurityAccess\\SeednKey_Opt_More.dll"));//LoadLibrary填入ddl文件名赋值给句柄printf("dll的句柄返回值%d\n", handle); //打印吧if (handle) //判读句柄内dll是否可用{
typedef int(*DLL_FUNCTION_GenerateKeyExOpt) (const unsigned char*, unsigned int, const unsigned int, const char*, const char*, unsigned char*, unsigned int, unsigned int&); //typedef定义一下函数指针,你不懂的话就记住末尾两个是你需要函数的形参。DLL_FUNCTION_GenerateKeyExOpt dll_GenerateKeyExOpt = (DLL_FUNCTION_GenerateKeyExOpt)GetProcAddress(handle, "GenerateKeyExOpt"); //使用GetProcAddress得到函数,参数是句柄名和函数名printf("dll_函数返回值%d\n", dll_GenerateKeyExOpt); //打印吧if (dll_GenerateKeyExOpt) //还是判断一下函数指针是否有效{
int result = dll_GenerateKeyExOpt(ipSeedArray, iSeedArraySize, iSecurityLevel, iVariant, ipOptions, ioKeyArray, iKeyArraySize, oSize);}FreeLibrary(handle); //卸载句柄,,}return 0;
}KEYGENALGO_API VKeyGenResultEx 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* iVariant, /* Name of the active variant [in] */const char* ipOptions,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] */)
{
int result;if (iSeedArraySize>iKeyArraySize)return KGRE_BufferToSmall;if (iSecurityLevel == 0x01){
result = GenerateKeyExOpt_new(ipSeedArray, iSeedArraySize, iSecurityLevel, iVariant, ipOptions, ioKeyArray, iKeyArraySize, oSize);}else if (iSecurityLevel == 0x11){
result = GenerateKeyExOpt_new(ipSeedArray, iSeedArraySize, iSecurityLevel, iVariant, ipOptions, ioKeyArray, iKeyArraySize, oSize);}else if (iSecurityLevel == 0x13){
for (unsigned int i = 0; i < iSeedArraySize; i++)ioKeyArray[i] = ipSeedArray[i] - 1;}else{
return KGRE_SecurityLevelInvalid;}oSize = iSeedArraySize; return KGRE_Ok;
}
? 二次封装后的DLL测试
3?? 生成新的DLL,重命名为 SeednKey _Opt_More_level13.dll
,拷贝到 SecurityAccess
文件路径下
4?? ,因为官方示例中诊断控制台没有 level 13的诊断定义,暂时手上也没有编辑工具,我们只能通过CAPL脚本测试下
- 在
DoorFL.can
中更改代码如下,当收到27 13
和27 14 xx xx
诊断请求的时候,给诊断仪响应
on diagRequest DoorFL.*
{
// ResetSession();
// diagSendNegativeResponse(this, cNRC_ServiceNotSupported); diagResponse DoorFL.SeedLevel_0x01_Request rqRequestSeed;diagResponse DoorFL.KeyLevel_0x01_Send rqKeytSeed;diagResponse this resp;long result_1,result_2;word random;result_1 = DiagGetPrimitiveByte(this,0);result_2 = DiagGetPrimitiveByte(this,1);write("*diagRequest*****result_1:%x ;result_2:%x ;*****",result_1,result_2);if ((result_1 == 0x27) && (result_2 == 0x13) ){
random=random(0x10000);write("****** random Seed is 0x%x ******",random);DiagSetPrimitiveByte(rqRequestSeed,0,0x27);DiagSetPrimitiveByte(rqRequestSeed,1,0x13);DiagSetPrimitiveByte(rqRequestSeed,2,random&0xFF);DiagSetPrimitiveByte(rqRequestSeed,3,(random>>8)&0xFF); rqRequestSeed.SendPositiveResponse() ; } if ((result_1 == 0x27) && (result_2 == 0x14) ){
DiagSetPrimitiveByte(rqKeytSeed,0,0x27);DiagSetPrimitiveByte(rqKeytSeed,1,0x14);rqKeytSeed.SendPositiveResponse() ; }
}
5?? 在TesterPanelControl.can
中更改代码如下:
- 按键‘b’ ,发送27 13请求。
- 当收到
27 13 xx xx
响应的种子时,计算key,然后 发送27 14 xx xx
on diagResponse DoorFL.*
{
// ResetSession();
// diagSendNegativeResponse(this, cNRC_ServiceNotSupported); diagRequest DoorFL.KeyLevel_0x01_Send reqKeySend;word seed;word securityKey;byte seedArray[2];byte keyArray[2];dword keyActualSizeOut;long result_1,result_2;word random;result_1 = DiagGetPrimitiveByte(this,0);result_2 = DiagGetPrimitiveByte(this,1);write("**diagResponse****result_1:%x ;result_2:%x ;*****",result_1,result_2);if ((result_1 == 0x27) && (result_2 == 0x13) ){
seedArray[0]=DiagGetPrimitiveByte(this,2);seedArray[1]=DiagGetPrimitiveByte(this,3);write("**diagResponse****seedArray[0]:%x ;seedArray[1]:%x ;*****",seedArray[0],seedArray[1]);diagGenerateKeyFromSeed(gECU, seedArray , 2, 0x13, "", "" , keyArray, elcount(keyArray), keyActualSizeOut); securityKey=(((word)keyArray[1])<<8) | keyArray[0];write("****** create key (27 02 send) is 22222 step exec ******");write("**diagResponse****keyArray[0]:%x ;keyArray[1]:%x ;*****",keyArray[0],keyArray[1]);DiagSetPrimitiveByte(reqKeySend,0,0X27);DiagSetPrimitiveByte(reqKeySend,1,0X14);DiagSetPrimitiveByte(reqKeySend,2,keyArray[0]);DiagSetPrimitiveByte(reqKeySend,3,keyArray[1]);// Checking on return values indicating an error when sending the requests or when receiving the responses was omitted here to simplify the examplereqKeySend.SendRequest();}
}On key 'b'
{
diagRequest DoorFL.SeedLevel_0x01_Request rqRequestSeed;diagRequest DoorFL.ExtendedDiagnosticSession_Start reqExtSession;reqExtSession.SendRequest(); DiagSetPrimitiveByte(rqRequestSeed,0,0x27);DiagSetPrimitiveByte(rqRequestSeed,1,0x13);rqRequestSeed.SendRequest();}
6?? 配置下新创建的DLL SeednKey _Opt_More_level13.dll
:
7?? 在诊断控制台 分别发送 1003 / 2701/2702/2711/2712
,控制台输出结果如下图,可以看出 level 1 和 11
的 seedkey
是能够正常响应的,没问题的。
8?? 按下按键’b‘ ,发送 27 13
,这里只能在write
窗口和 trace
中观察结果,key
值计算正确的。这说明通过二次封装DLL成功了。
9?? 如果遇到生成的DLL,在有的电脑上可以使用,有的不行,试试下面的选项。
End |
?总结
? 有需要演示中所用demo工程的,可以关注下方公众号网盘自取啦,感谢阅读。
- ?要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!
- ? 有手机的小伙伴可以加下交流群,在车载诊断领域的一个小小圈子,群里有
网盘资料
,源码
,可能有你需要的呢,平时可以交流技术,聊聊工作机会啥的。
- ?如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。