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

📙 相关文章

在这里插入图片描述


📘前言

相关文章

  • 实际工程中,会产生这种情况,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 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 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 和 11seedkey 是能够正常响应的,没问题的。

在这里插入图片描述


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

在这里插入图片描述


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

在这里插入图片描述

在这里插入图片描述

End

🌎总结

23

请添加图片描述

🍅 有需要演示中所用demo工程的,可以关注下方公众号网盘自取啦,感谢阅读。
7

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

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

  • 🚩如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。
    18
  • 10
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蚂蚁小兵

慢慢长夜磨一章好文章,费烟!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值