📙 相关文章
📘前言
相关文章
-
实际工程中,会产生这种情况,OEM给了你seedkey.dll ,没有给你具体算法,因为它不希望自己密钥泄露,作为供应商,还有自己的sub function,这个时候,我们就需要在OEM提供的DLL基础上,再封装一层。
-
这里博主强烈建议你先阅读 🚩CANoe DLL编程(五)——通过VS 生成 SendKey.dll内容基于它扩展开来的
-
软件环境:
win10 x64
visual studio 2019
CANoe 11 x64
📙 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 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();
}
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工程的,可以关注下方公众号网盘自取啦,感谢阅读。
- 🚩要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!
- 🚩 有手机的小伙伴可以加下交流群,在车载诊断领域的一个小小圈子,群里有
网盘资料
,源码
,可能有你需要的呢,平时可以交流技术,聊聊工作机会啥的。
- 🚩如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。