CANoe DLL编程—— DLL 的二次封装
Posted 蚂蚁小兵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 ,没有给你具体算法,因为它不希望自己密钥泄露,作为供应商,还有自己的subfunction,这个时候,我们就需要在OEM提供的DLL基础上,再封装一层。
-
这一节内容依赖 CANoe DLL编程(一)的内容,请先阅读,再看这一节。
-
软件环境:
win10 x64
visual studio 2019
CANoe 11 x64
增加 27服务 13 subfunction
①,这里假设我们之前生成的DLL SeednKey_Opt_More.dll
是客户给的,seedkey 的算法是保密的,只有level1和level 11,现在我们要把自己的level 13加进去`
- 我们把
KeyGenDll_GenerateKeyEx - Copy
拷贝一份KeyGenDll_GenerateKeyEx_Level_13
②,我们完善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,重命名为
SeednKey _Opt_More_level13.dll
,拷贝到SecurityAccess
文件路径下
③,因为官方示例中诊断控制台没有 level 13的诊断定义,暂时手上也没有编辑工具,我们只能在simulation node脚本中处理下:
- 在
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() ;
}
}
- 在
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 example
reqKeySend.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();
}
④,配置下新创建的DLL SeednKey _Opt_More_level13.dll
:
- 在诊断控制台 分别发送
1003 / 2701/2702/2711/2712
,控制台输出结果如下图,可以看出level 1 和 11
的seedkey
是能够正常响应的,没问题的。
- 按下按键’b‘ ,发送
27 13
,这里只能在write
窗口和trace
中观察结果,key
值计算正确的。这说明通过二次封装DLL成功了。
总结
- 要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!
- 如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。
以上是关于CANoe DLL编程—— DLL 的二次封装的主要内容,如果未能解决你的问题,请参考以下文章
CANoe DLL编程—— 创建CANoe适用的DLL以及调用
CANoe DLL编程——SendKey DLL的CANoe应用