当前位置: 代码迷 >> 综合 >> CANoe DLL编程(六)—— DLL文件的二次封装
  详细解决方案

CANoe DLL编程(六)—— DLL文件的二次封装

热度:76   发布时间:2023-09-20 13:11:38.0

? 相关文章

CANoe DLL编程(六)—— DLL文件的二次封装

  • ?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

CANoe DLL编程(六)—— DLL文件的二次封装

文章目录

  • ? 相关文章
  • ?前言
  • 相关文章
  • ? DLL二次封装代码解读
  • ? 二次封装后的DLL测试
  • ?总结

CANoe DLL编程(六)—— DLL文件的二次封装

? DLL二次封装代码解读

1?? 这里假设我们之前生成的DLL SeednKey_Opt_More.dll 是客户给的,seedkey 的算法是保密的,只有level1和level 11,现在我们要把自己的level 13加进去`

  • 我们把 KeyGenDll_GenerateKeyEx - Copy 拷贝一份KeyGenDll_GenerateKeyEx_Level_13

CANoe DLL编程(六)—— DLL文件的二次封装


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文件路径下

CANoe DLL编程(六)—— DLL文件的二次封装


4?? ,因为官方示例中诊断控制台没有 level 13的诊断定义,暂时手上也没有编辑工具,我们只能通过CAPL脚本测试下

  • DoorFL.can 中更改代码如下,当收到 27 1327 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

CANoe DLL编程(六)—— DLL文件的二次封装


7?? 在诊断控制台 分别发送 1003 / 2701/2702/2711/2712 ,控制台输出结果如下图,可以看出 level 1 和 11seedkey 是能够正常响应的,没问题的。

CANoe DLL编程(六)—— DLL文件的二次封装


8?? 按下按键’b‘ ,发送 27 13,这里只能在write 窗口和 trace 中观察结果,key值计算正确的。这说明通过二次封装DLL成功了。

CANoe DLL编程(六)—— DLL文件的二次封装


9?? 如果遇到生成的DLL,在有的电脑上可以使用,有的不行,试试下面的选项。

CANoe DLL编程(六)—— DLL文件的二次封装

CANoe DLL编程(六)—— DLL文件的二次封装

End

?总结

CANoe DLL编程(六)—— DLL文件的二次封装

CANoe DLL编程(六)—— DLL文件的二次封装

? 有需要演示中所用demo工程的,可以关注下方公众号网盘自取啦,感谢阅读。
CANoe DLL编程(六)—— DLL文件的二次封装

  • ?要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!

  • ? 有手机的小伙伴可以加下交流群,在车载诊断领域的一个小小圈子,群里有网盘资料源码,可能有你需要的呢,平时可以交流技术,聊聊工作机会啥的。

  • ?如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。
    CANoe DLL编程(六)—— DLL文件的二次封装