搜索
bottom↓
回复: 46

【悬赏200汤圆】STM32 唯一ID加密这样处理作用大不大

[复制链接]

出675入8汤圆

发表于 2021-2-20 11:44:51 | 显示全部楼层 |阅读模式
200汤圆
参考帖子:https://blog.csdn.net/meifan2010/article/details/102966511

程序需要烧录两次,第一次烧录的加密程序,然后将结果存入FLASH ,第二次是应用程序+解密 ,将解密结果与存入FLASH的结果比较是否成功。

uint32_t m_ui32AdressVar = 0XEA60;
static void board_get_uniid(uint32_t *IntDeviceSerial)
{
  //不直接通过0x1FFFF7E8 地址读取UID,而是先通过数据算出UID地址,0x1FFFF7E8 = (((m_ui32AdressVar<<10) + 0x567EFD)<<3)
  uint32_t *UniIdAdress;
  UniIdAdress = (uint32_t*)(((m_ui32AdressVar<<10) + 0x567EFD)<<3);//0x1FFFF7E8 指针UniIdAdress
       
  IntDeviceSerial[0] = *(__IO uint32_t*)(UniIdAdress) + 0x4321;
  IntDeviceSerial[1] = *(__IO uint32_t*)(UniIdAdress+0x04) + 0x1234;//+0x04
  IntDeviceSerial[2] = *(__IO uint32_t*)(UniIdAdress+0x08) + 0x5555;//+0x08
       
//  IntDeviceSerial[0] = *(__IO uint32_t*)(0x1FFFF7E8);
//  IntDeviceSerial[1] = *(__IO uint32_t*)(0x1FFFF7EC);//+0x04
//  IntDeviceSerial[2] = *(__IO uint32_t*)(0x1FFFF7F0);//+0x08
}

通过上面这样处理意义大吗?如果直接读取UID,网友说反汇编很快就找到唯一ID地址并直接跳过了,我不知道通过上面这样转换一下,是不是没有那么容易破解。

希望各位探头,指教一个好一点的防止破解的方法

最佳答案

查看完整内容

我以前写过一个 比这个稍微强点 可以防大部分的吧 就算破解 也略微费点功夫 思路利用stm32里全球唯一ID 加一个CRC16+EEPROM 也可以再加FLASH读保护 1.第一次上电流程:判断是不是第一次上电(FLASH里都是0xFF)如果是那就在自定义地址写入ID+CRC16 有EEPROM也一块写入 2.以后开机流程:直接比对STM32里的ID和FLASH里的ID 和EEPROM的ID是否完全一样 三方对比 3.不一致没必要不运行或者while(1),可以让他偶尔出一次故障 ...

阿莫论坛20周年了!感谢大家的支持与爱护!!

如果天空是黑暗的,那就摸黑生存;
如果发出声音是危险的,那就保持沉默;
如果自觉无力发光,那就蜷伏于牆角。
但是,不要习惯了黑暗就为黑暗辩护;
也不要为自己的苟且而得意;
不要嘲讽那些比自己更勇敢的人。
我们可以卑微如尘土,但不可扭曲如蛆虫。

出0入16汤圆

发表于 2021-2-20 11:44:52 | 显示全部楼层
本帖最后由 射天狼 于 2021-2-24 08:50 编辑

我以前写过一个 比这个稍微强点 可以防大部分的吧 就算破解 也略微费点功夫
思路利用stm32里全球唯一ID 加一个CRC16+EEPROM  也可以再加FLASH读保护
1.第一次上电流程:判断是不是第一次上电(FLASH里都是0xFF)如果是那就在自定义地址写入ID+CRC16 有EEPROM也一块写入
2.以后开机流程:直接比对STM32里的ID和FLASH里的ID 和EEPROM的ID是否完全一样 三方对比
3.不一致没必要不运行或者while(1),可以让他偶尔出一次故障
  1. //////////////////////加密程序开始//////////////////////
  2. #define EEPROM
  3. //        FLASH_Unlock();
  4. ////  FLASH_ReadOutProtection(DISABLE);
  5. //        FLASH_ReadOutProtection(ENABLE);//读输出保护
  6. //        FLASH_Lock();
  7. #ifdef EEPROM
  8. WP_L;   //读取EEPROM里的ID和CRC
  9. for(i=0; i<14; i++) {
  10.     I2C_ReceiveData(0xA2,0x1000+i, HAV_H,&UID_E[i], 1);//u8
  11. }
  12. WP_H;
  13. #endif
  14. Get_ChipID();
  15. crc = crc16_ccitt(UID, 12); //校验前12个字节 最后两个字节CRC16校验
  16. UID[12]=(*(char *)(&crc));
  17. UID[13]=(*((char *)(&crc) + 1));

  18. STMFLASH_Read(0x803FF00,(u16*)UID_F,7); //最后一个16个字节是CRC16校验
  19. //        check(1, &UID_F[0],12));
  20. crc = crc16_ccitt(UID_F, 12); //校验前12个字节 最后两个字节CRC16校验
  21. UID_F[12]=(*(char *)(&crc));
  22. UID_F[13]=(*((char *)(&crc) + 1));

  23. //        Unique_temp=*(vu32 *)UID_F;//stm32小端 0x12 0x34 0x56 0x78 Unique_temp为0x78563412

  24. //如果FLASH是第一次下载 先写入读取的ID到FLASH和EEPROM
  25. if(UID_F[0]==0xff && UID_F[1]==0xff && UID_F[2]==0xff && UID_F[3]==0xff) {
  26.     STMFLASH_Write(0x803FF00,(u16*)UID,7);
  27. #ifdef EEPROM
  28.     //也写一次EEPROM 三方对比
  29.     WP_L;   //保存校准值到eeprom
  30.     for(i=0; i<14; i++) {
  31.         I2C_SendData(0xA2,0x1000+i, HAV_H,&UID[i], 1);//u8
  32.     }
  33.     WP_H;
  34. #endif
  35. } else { //开始对比ID和FLASH、EEPROM是否相同
  36.     for(i=0; i<14; i++) {
  37.         if(UID[i]!=UID_F[i]) {
  38.             display_string_12x32(68,2, "ERROR",5,0);
  39.             while(1);
  40.         }
  41.     }
  42. #ifdef EEPROM
  43.     for(i=0; i<14; i++) {
  44.         if(UID[i]!=UID_E[i]) {
  45.             display_string_12x32(68,2, "ERROR",5,0);
  46.             while(1);
  47.         }
  48.     }
  49. #endif
  50. }
  51. //////////////////////加密程序结束//////////////////////
复制代码




出675入8汤圆

 楼主| 发表于 2021-2-20 11:51:05 | 显示全部楼层
http://www.amobbs.com/thread-5518980-1-1.html 这个帖子好像很有用,莫大能回复一下吗 ?

出0入59汤圆

发表于 2021-2-20 12:12:25 | 显示全部楼层
M 核最支持读存储器某个地址时触发断点,所以你这方法也是防君子

出0入8汤圆

发表于 2021-2-20 13:28:15 | 显示全部楼层
防低手不防高手,防抄板破解,不防仿功能重写

出0入8汤圆

发表于 2021-2-20 17:20:26 来自手机 | 显示全部楼层
本帖最后由 canspider 于 2021-2-20 17:23 编辑

毫无意义,破解的第一步就是找出访问唯一ID的代码,重定向到假唯一ID

你认为的找读ID的代码:反编译分析,费时间
实际上找读ID的代码:下内存断点,根本不会管你是怎么混淆计算的

出0入1209汤圆

发表于 2021-2-20 17:49:06 | 显示全部楼层
canspider 发表于 2021-2-20 17:20
毫无意义,破解的第一步就是找出访问唯一ID的代码,重定向到假唯一ID

你认为的找读ID的代码:反编译分析, ...

你没看懂楼主的操作,楼主代码里根本就没有读ID,而是去读了另外一个flash地址。这个flash地址里存了根据ID计算出来的数值。

出0入8汤圆

发表于 2021-2-20 17:53:56 来自手机 | 显示全部楼层
kitten 发表于 2021-2-20 17:49
你没看懂楼主的操作,楼主代码里根本就没有读ID,而是去读了另外一个flash地址。这个flash地址里存了根据 ...

如果不去读芯片的唯一ID,那靠什么来区分是正版还是盗版的呢

出675入8汤圆

 楼主| 发表于 2021-2-20 18:01:36 | 显示全部楼层
kitten 发表于 2021-2-20 17:49
你没看懂楼主的操作,楼主代码里根本就没有读ID,而是去读了另外一个flash地址。这个flash地址里存了根据 ...

0x1FFFF7E8  这个就是UID的地址哦

出675入8汤圆

 楼主| 发表于 2021-2-20 18:03:10 | 显示全部楼层
现在的问题变成了怎样隐藏式的去读Uid,让破解者监控不到 ,当然,我的程序UID校验不合格也不会死机,会修改一些参数,不影响程序运行,性能会降低而已

出0入8汤圆

发表于 2021-2-20 18:12:32 来自手机 | 显示全部楼层
xml2028 发表于 2021-2-20 18:03
现在的问题变成了怎样隐藏式的去读Uid,让破解者监控不到 ,当然,我的程序UID校验不合格也不会死机,会修改 ...

普通的STM32做不到,CortexM33内核的单片机可以做到

出140入158汤圆

发表于 2021-2-20 18:27:22 | 显示全部楼层
好过没有一屌屌

出675入8汤圆

 楼主| 发表于 2021-2-20 20:24:03 | 显示全部楼层
上面的程序的寻址方式使用不对,不知道为什么,改成下面这样就OK了
  uint32_t *UniIdAdress1;
  uint32_t *UniIdAdress2;
  uint32_t *UniIdAdress3;
  UniIdAdress1 = (uint32_t*)(((m_ui32AdressVar<<10) + 0x567EFD)<<3);//0x1FFFF7E8 µØÖ·ÏÈתÒÆÖÁUniIdAdress
  UniIdAdress2 = (uint32_t*)((((m_ui32AdressVar<<10) + 0x567EFD)<<3) + 4);
  UniIdAdress3 = (uint32_t*)((((m_ui32AdressVar<<10) + 0x567EFD)<<3) + 8);
  
  IntDeviceSerial[0] = *( uint32_t*)(UniIdAdress1) + 0x0819;
  IntDeviceSerial[1] = *( uint32_t*)(UniIdAdress2) + 0x0322;//+0x04
  IntDeviceSerial[2] = *( uint32_t*)(UniIdAdress3) + 0x0425;//+0x08

出675入8汤圆

 楼主| 发表于 2021-2-20 20:25:04 | 显示全部楼层
static void board_get_uniid(uint32_t *IntDeviceSerial)
{
  //不直接通过0x1FFFF7E8 地址读取UID,而是先通过数据算出UID地址,0x1FFFF7E8 = (((m_ui32AdressVar<<10) + 0x567EFD)<<3)
  uint32_t *UniIdAdress;
  UniIdAdress = (uint32_t*)(((m_ui32AdressVar<<10) + 0x567EFD)<<3);//0x1FFFF7E8 指针UniIdAdress
      
  IntDeviceSerial[0] = *(__IO uint32_t*)(UniIdAdress) + 0x4321;
  IntDeviceSerial[1] = *(__IO uint32_t*)(UniIdAdress+0x04) + 0x1234;//+0x04
  IntDeviceSerial[2] = *(__IO uint32_t*)(UniIdAdress+0x08) + 0x5555;//+0x08

这样读取UID的结果是不对的,各位能指教一下吗

出0入0汤圆

发表于 2021-2-21 08:54:05 | 显示全部楼层
LZ的方法可行的, 但要注意, 软件不要上来就读ID作判断, ID的3*32位也不要在一段代码中读取, 只有在某些条件满足时才去读ID,  判断ID是否正确也同样(最好融入程序的算法中), 这样可以大大提高破解难度.

出10入95汤圆

发表于 2021-2-21 09:02:37 | 显示全部楼层
有一个为了防破解,而伤透脑筋:)
刷两边程序,增加工作量啊。

出675入8汤圆

 楼主| 发表于 2021-2-21 13:43:30 来自手机 | 显示全部楼层
ddcour 发表于 2021-2-21 09:02
有一个为了防破解,而伤透脑筋:)
刷两边程序,增加工作量啊。

产品往往没那么大量,增加点时间无所谓,人工费并没有那么贵

出0入0汤圆

发表于 2021-2-21 13:51:30 | 显示全部楼层
让程序自已算,算完了再把算的程序擦除。随机读ID(机率很小)。不对就自杀或把硬件烧毁。

出0入0汤圆

发表于 2021-2-21 17:00:22 | 显示全部楼层
还要注意内存断点

混淆的方法是 用4KB内存填充随机数,加密信息有规律随机放在里面

出0入18汤圆

发表于 2021-2-21 17:02:53 来自手机 | 显示全部楼层
canspider 发表于 2021-2-20 18:12
普通的STM32做不到,CortexM33内核的单片机可以做到

m33是靠什么机制来保证的?

出0入18汤圆

发表于 2021-2-21 17:05:03 来自手机 | 显示全部楼层
我感觉只要定位到访问uid的代码,重定向到其它伪uid的地址,啥加密都没用

出20入0汤圆

发表于 2021-2-21 23:59:53 | 显示全部楼层
有些烧录软件可以读UID然后根据规则变换写到FLASH,应该程序可以读这个地址而不用读UID是否更完美?

出0入8汤圆

发表于 2021-2-22 09:06:15 来自手机 | 显示全部楼层
tang_qianfeng 发表于 2021-2-21 17:02
m33是靠什么机制来保证的?

这个论坛有人介绍过M33内核,不过曲高和寡,几乎没人能看明白,如果你想了解可以翻来看看

出675入8汤圆

 楼主| 发表于 2021-2-22 13:08:54 来自手机 | 显示全部楼层
cantonguy 发表于 2021-2-21 23:59
有些烧录软件可以读UID然后根据规则变换写到FLASH,应该程序可以读这个地址而不用读UID是否更完美? ...

不行的,破解首先就是复制你的flash,你这样做有何意义?

出20入0汤圆

发表于 2021-2-22 13:39:12 | 显示全部楼层
xml2028 发表于 2021-2-22 13:08
不行的,破解首先就是复制你的flash,你这样做有何意义?

哈哈,也是

这么说凡是逆向懂的,其实真的很容易破解了

出0入0汤圆

发表于 2021-2-22 17:21:59 | 显示全部楼层
没有用处,只要你出现了对唯一ID的访问地址,就可以直接替换来破解。

出0入18汤圆

发表于 2021-2-22 18:49:38 来自手机 | 显示全部楼层
canspider 发表于 2021-2-22 09:06
这个论坛有人介绍过M33内核,不过曲高和寡,几乎没人能看明白,如果你想了解可以翻来看看 ...

是不是用的copryto?

出0入8汤圆

发表于 2021-2-22 22:03:21 来自手机 | 显示全部楼层
多放几个其他类型mcu,增加破解成本,哈哈

出0入0汤圆

发表于 2021-2-23 10:10:55 | 显示全部楼层
你可以加上对固件进行校验措施,这样对方改动程序里的任何字符都可以发现的。不要做完整校验,校验包含地址访问的那一段,这样破解还需要找出你的校验起始和结束地址,应该会增加些破解难度的。

出0入0汤圆

发表于 2021-2-23 10:43:37 | 显示全部楼层
单机版本的 ,基本不起什么作用,防新手和小白应该可以。
联网版本的,可以再加一点别的东西,把设备合法性,放一部分工作在服务器上,设备端越简单越好

出675入8汤圆

 楼主| 发表于 2021-2-23 13:15:41 来自手机 | 显示全部楼层
iwinstone 发表于 2021-2-23 10:10
你可以加上对固件进行校验措施,这样对方改动程序里的任何字符都可以发现的。不要做完整校验,校验包含地址 ...

如何实现呢

出0入0汤圆

发表于 2021-2-23 14:04:20 | 显示全部楼层
1.在虚拟机里读ID和判断,相当于混淆了代码,反汇编都困难
2. 不要每次上电都读ID和判断,弄成随机的,有延时的。比如上电100次才判断一次,几天判断一次

出0入0汤圆

发表于 2021-2-23 14:14:28 | 显示全部楼层
iwinstone 发表于 2021-2-23 10:10
你可以加上对固件进行校验措施,这样对方改动程序里的任何字符都可以发现的。不要做完整校验,校验包含地址 ...

这样几乎没有增加难度,找到最终判断的指令,改成无论对错都跳转正确分支就可以了。这种校验一般是用来防止程序烧写错误,对防破解没什么用

出0入0汤圆

发表于 2021-2-23 18:14:40 | 显示全部楼层

定义一个常量到固定地址,作为存放校验码用,如果系统有Bootloader,则可以不定义,将校验码存放在Boot和主程序中间的空闲空间。
程序中读取一段固件内容,这段内容要包括进行唯一ID读取访问的那部分,(可以在编译后进行搜索唯一ID的地址来确定位置,找到后在程序中确定校验起始和结束地址,然后再次编译),进行校验,和最终校验值进行比较。
校验值在电脑中用相同算法使用编译好的固件内容进行计算,计算好后用二进制编辑器写入到编译好的二进制文件的预留位置,形成最终二进制文件。

出0入0汤圆

发表于 2021-2-23 18:17:53 | 显示全部楼层
nanfang2000 发表于 2021-2-23 14:14
这样几乎没有增加难度,找到最终判断的指令,改成无论对错都跳转正确分支就可以了。这种校验一般是用来防 ...

如何找到最终判断指令,程序中跳转指令很多,怎么确定哪个是我们校验的跳转,单纯唯一ID破解是依靠唯一ID地址为关键词进行搜索,再进行相关修改。

出0入93汤圆

发表于 2021-2-23 19:07:31 | 显示全部楼层
iwinstone 发表于 2021-2-23 18:17
如何找到最终判断指令,程序中跳转指令很多,怎么确定哪个是我们校验的跳转,单纯唯一ID破解是依靠唯一ID ...

就是,反正最后都是防君子不防小人,那就让他们的难度大一点。在您这个基础上锦上添花一把:
1、0x1FFFF7E8 这个就是UID的地址,那么如果MCU支持非对齐访问(M3以上)的我们改为访问0x1FFFF7E9,这样避开了常用的内存断点0x1FFFF7E8
2、读取UID的函数做成强制内联,到处调用,一处改了其他地方未必改了
3、对固件进行校验,校验值不进行判断而是硬编码为一个常数(宏),MCU中涉及到常数的地方(比如寄存器赋值、循环变量等)都异或这个宏然后再异或校验函数。反正LZ的人工费不值钱,那就每一个MCU都重新编译一遍。或者写个脚本去替换。

出0入0汤圆

发表于 2021-2-23 21:34:23 | 显示全部楼层
能否这样?纯猜想,没试过:
1. UID地址 0x1FFFF7E8 先用 0x1FFFF7E0 等代替,同时也隐藏 0x1FFFF7E0 这个UID附近的值,需要计算才能得出;
2. 得到0x1FFFF7E0这个值后,用DMA去读取0x1FFFF7E0及后面的一段内容(覆盖到UID就行);
3. 程序里一些复杂算法等,做到和UID相关,UID不对也能用,但会影响效果、精度等;

如果产品本身不够复杂,简单做做防抄袭手段就行了,毕竟仿制成本也低。

出675入8汤圆

 楼主| 发表于 2021-2-23 22:46:45 | 显示全部楼层
nanfang2000 发表于 2021-2-23 14:04
1.在虚拟机里读ID和判断,相当于混淆了代码,反汇编都困难
2. 不要每次上电都读ID和判断,弄成随机的,有延 ...

我现在就是这样处理的,运行一段时间才校验ID

出675入8汤圆

 楼主| 发表于 2021-2-23 22:49:05 | 显示全部楼层
amdzid 发表于 2021-2-23 21:34
能否这样?纯猜想,没试过:
1. UID地址 0x1FFFF7E8 先用 0x1FFFF7E0 等代替,同时也隐藏 0x1FFFF7E0 这个U ...

网友不是说内存断电能监测得到读ID吗,DMA读取就不会触发内存断电了吗 ?

出675入8汤圆

 楼主| 发表于 2021-2-23 22:52:02 | 显示全部楼层
takashiki 发表于 2021-2-23 19:07
就是,反正最后都是防君子不防小人,那就让他们的难度大一点。在您这个基础上锦上添花一把:
1、0x1FFFF7 ...

人工费不用钱也没你说的这么夸张哦,我说的人工费不值钱是正常一个工人一天能烧录3000-4000片,我烧录两次,变成烧录2000片了我也能接受这个效率,毕竟 没有那么大量,你说的这个每个MCU都编译一次,这相当于产品不能转产啊

出0入0汤圆

发表于 2021-2-23 23:38:57 | 显示全部楼层
本帖最后由 ttimasdf 于 2021-2-23 23:42 编辑

我之前是做传统领域的软件安全的。security by obscurity 在几十年前就被证明是最不可取的办法。对于软件逆向的对抗思路,一般来讲是这样的。

1. 假定你的一切源代码(包括编译得到的汇编bytecode),加密密钥都是可以被攻击者获取的。
2. 在1的基础之上,明确的告诉攻击者(当然也可以不告诉攻击者),逆向工程的成本将会大于等于重新开发的成本。

这就足够了。

楼主现在采用的方式,其实类似于古典密码,只能线性的增加一点点攻击者的逆向成本(比如从1天变成5天)。可以尝试寻找一些其他方法(当然如果成本允许的话,包括硬件成本和技术开发成本),指数级提高攻击者的逆向难度。当然这些方法对开发者的技术要求也非常高,而且我不确定单片机从软件上实现这些,性能能不能扛得住。所以我只是抛砖引玉一下哈,

1. 采用类似 Obfuscator-LLVM 的方式保护负责固件解密的子函数,具体实现就是在固件编译过程中,在程序运行控制流上做一些文章,这个强度的保护下,没有编译器知识的工具小子是不可能还原出原始代码的。
2. 基于已有的现代密码学算法,但是对加解密过程进行一定的修改(特别是加解密过程中所使用到的常量)。楼主可以在 https://github.com/polymorf/find ... er/findcrypt3.rules 这里找到我们(作为攻击者)常用的一些寻找解密算法常量的特征规则,包括AES、DES等等加密算法和MD5、SHA256等等哈希算法,都很容易找的。因此对称加密算法理论上直接拿来用的话,很容易被人破解。
3. 使用 Argon2 等密钥延申算法 (https://en.wikipedia.org/wiki/Key_stretching) ,在运行进行真正的解密过程前,对密钥进行延展变换(在现在的语境下,密钥就是从硬件上读出来的ID)。毕竟攻击者拿不到符号,是看不出密钥变换和解密函数中间的边界的,不过如果不禁用调试功能,攻击者除了静态分析还能进行打断点读内存的话,这个方法的保护强度就会弱很多了。

不过还是那句话,如果想防御更高水平的攻击者,就得付出更高的安全成本,上面说的都是从软件层面解决,比较麻烦,从硬件层面换个芯片可能更容易,我之前在的公司就有专门做软件防破解的产品 要¥¥¥的话就比较伤心啦

出0入8汤圆

发表于 2021-2-24 08:16:41 来自手机 | 显示全部楼层
ttimasdf 发表于 2021-2-23 23:38
我之前是做传统领域的软件安全的。security by obscurity 在几十年前就被证明是最不可取的办法。对于软件逆 ...


能有这种认识的人不会只搞单片机开发,早就转工资更高的纯软件或是走管理路线了。
因此比较深入的软件工程问题不适合在单片机开发群体中讨论。

出0入0汤圆

发表于 2021-2-24 10:00:51 | 显示全部楼层
iwinstone 发表于 2021-2-23 18:17
如何找到最终判断指令,程序中跳转指令很多,怎么确定哪个是我们校验的跳转,单纯唯一ID破解是依靠唯一ID ...

有反汇编,稍微看一下或者跟踪调试一下就知道了。比直接搜ID要难点,但是难的不多

出0入0汤圆

发表于 2021-2-24 10:16:25 | 显示全部楼层
还有个办法,换国产兼容芯片,应该可以增加破解成本

出0入0汤圆

发表于 2021-2-24 10:47:40 | 显示全部楼层
xml2028 发表于 2021-2-23 22:46
我现在就是这样处理的,运行一段时间才校验ID

你这样足够了,隐式读ID,延迟、随机校验,校验失败也不直接发作(就像你说的只降低性能或者随机crash),已经把破解难度提高两个数量级了。
再加一条,不要只写一个读ID和校验函数,写上5,6个不同的函数,在不同的情况下调用。保证破解者调到吐血

没有带可信硬件的单片机,无论搞什么加密算法都不如用上面说的这种多校验多暗桩

出0入0汤圆

发表于 2021-2-24 12:44:56 | 显示全部楼层
支持留暗坑破解后随机十天半个月的 直接烧鸡

出675入8汤圆

 楼主| 发表于 2021-2-24 20:50:17 | 显示全部楼层
nanfang2000 发表于 2021-2-24 10:47
你这样足够了,隐式读ID,延迟、随机校验,校验失败也不直接发作(就像你说的只降低性能或者随机crash) ...

谢谢你的指教
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-9-27 07:12

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表