搜索
bottom↓
回复: 230

人人都能拿到jlink v9的bootloader

  [复制链接]

出0入0汤圆

发表于 2016-6-25 23:12:21 | 显示全部楼层 |阅读模式
本帖最后由 thxlp 于 2016-6-25 23:12 编辑

v10也出来了,v9也快没人用了?现在发个研究贴不违规吧?

v9里面大家最关心的就是bootloader了吧?
论坛上有很多前辈都给出了各种办法把这个bootloader弄出来,可是都是片言只语,所以这里我整理一下大概的两个办法。

首先是个最简单的办法,不用拆机,没有风险,原理很简单,很多年前论坛上的大牛就发现并公布了这个办法,不过据说后来论坛浮云过一回,资料丢了。
这个办法利用的是jlink自带的一个命令,这个命令能读取jlink自身的内存,我们只是需要用这个命令把bootloader部分的内容读取出来就可以了。

在进入这个具体命令之前,我们来看一下jlink的操纵方法,比较普遍的做法是调用jlinkarm.dll公开的接口,再有sdk的情况下,调用这些接口并不麻烦,
但是如果没有sdk的话,c/c++语言要调用这些接口显得特别的麻烦,所以这里我们使用更为底层的办法越过jlink的dll,直接和jlink的驱动打交道。

首先,我们需要找到系统里面的jlink这个设备
  1. GUID classGuid = {0x54654E76, 0xdcf7, 0x4a7f, 0x87, 0x8A, 0x4E, 0x8F, 0x0CA, 0x0A, 0x0CC, 0x9A};
  2. auto devInfoSet = SetupDiGetClassDevsW(&classGuid, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
复制代码
用上面的代码先找到jlink的class

然后我们需要枚举这个devInfoSet里面的全部成员,依次取得各种信息,最终拿到jlink驱动提供的设备路径
  1. SP_DEVICE_INTERFACE_DATA interfaceData = {0};
  2. interfaceData.cbSize = sizeof(interfaceData);
  3. for(DWORD i = 0; ; i ++)
  4. {
  5.     if(!SetupDiEnumDeviceInterfaces(devInfoSet, nullptr, &classGuid, i, &interfaceData))
  6.         break;

  7.     DWORD requiredSize = 0;
  8.     SetupDiGetDeviceInterfaceDetailW(devInfoSet, &interfaceData, nullptr, 0, &requiredSize, nullptr);
  9.     void* tempBuffer = new uint8_t[requiredSize];
  10.     PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData = static_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(tempBuffer);
  11.     interfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  12.     if(!SetupDiGetDeviceInterfaceDetailW(devInfoSet, &interfaceData, interfaceDetailData, requiredSize, &requiredSize, nullptr))
  13.         continue;
复制代码
到了这里interfaceDetailData->DevicePath这个里面就是jlink的设备路径,我们打开它
  1.     HANDLE deviceFile = CreateFileW(interfaceDetailData->DevicePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  2.     if(deviceFile == INVALID_HANDLE_VALUE)
  3.         continue;
复制代码
这个打开的文件句柄主要是给jlink发送一些控制命令,真正读写的是需要打开另外两个句柄的,pipe00用来读,pipe01用来写,我们也打开它们
  1.     wchar_t pipeFileName[1024] = {0};
  2.     wcscpy_s(pipeFileName, interfaceDetailData->DevicePath);
  3.     wcscat_s(pipeFileName, L"\\pipe00");
  4.     HANDLE readPileFile = CreateFileW(pipeFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  5.     if(readPileFile == INVALID_HANDLE_VALUE)
  6.         continue;

  7.     wcscpy_s(pipeFileName, interfaceDetailData->DevicePath);
  8.     wcscat_s(pipeFileName, L"\\pipe01");
  9.     HANDLE writePileFile = CreateFileW(pipeFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  10.     if(writePileFile == INVALID_HANDLE_VALUE)
  11.         continue;
复制代码
到了这里我们拿到了三个句柄,接下来我们就可以用这三个句柄来操控jlink了

首先介绍一下jlink的各种协议,这个协议有一部分公开了在它官网上,还有一个部分没有公开,大家可以去官网看看那个公开的文档,这里简单介绍一下。
jlink的协议比较简单,当我们需要做某件事情的时候,就往jlink发送一个命令过去,jlink解析我们发送的命令,处理,并返回一个结果(也有许多命令不返回结果)
我们发送给jlink的命令通过WriteFile函数调用写入到pipe01里面,然后通过读取pipe00获得命令结果。
jlink的数据使用stream的模式读写,在满足一定的延时要求的情况下,我们可以将一个命令分成几截写入,也可以按批次读取结果,下面我们就用一个简单的命令来举个例子。
这个命令用来获取jlink的固件版本,是一个公开的命令。
首先我们发送单字节的01到jlink
jlink会返回0x72个字节的内容给我们,前面两个字节是le格式的长度=0x70,表示这之后还要0x70个字节,这0x70个字节就是真正的内容。
  1. bool jlinkCommandReadFirmwareVersion(HANDLE readPipeFile, HANDLE writePipeFile, void* dataBuffer)
  2. {
  3.             uint8_t commandBuffer[1] = {0x01};
  4.             uint16_t leftLength = 0;
  5.             if(!jlinkSendCommand(readPipeFile, writePipeFile, commandBuffer, sizeof(commandBuffer), &leftLength, sizeof(leftLength)))
  6.                         return false;

  7.             return jlinkContinueReadResult(readPipeFile, dataBuffer, leftLength);
  8. }
复制代码
这里使用了两个函数,这两个函数下面会介绍,先看看这个函数的内容。
首先我们调用jlinkSendCommand发送1个字节的0x01给jlink,并读回两个字节的内容,这两个字节的内容=0x70,也就是剩余的数据大小,然后我们调用jlinkContinueReadResult把剩下的内容读全了。
注意,上面说过jlink使用的是stream模式,这就意味着,如果我没有未读完的数据还在jlink的缓冲区里面,那么这些内容会出现在下一条命令的返回结果里面,这里要特别小心。
  1. bool jlinkSendCommand(HANDLE readPipeFile, HANDLE writePipeFile, void const* commandBuffer, uint32_t commandLength, void* resultBuffer, uint32_t resultHeaderLength)
  2. {
  3.      if(!WriteFile(writePipeFile, commandBuffer, commandLength, nullptr, nullptr))
  4.         return false;

  5.     if(!resultHeaderLength)
  6.         return true;

  7.         return !!ReadFile(readPipeFile, resultBuffer, resultHeaderLength, nullptr, nullptr);
  8. }

  9. bool jlinkContinueReadResult(HANDLE readPipeFile, void* resultBuffer, uint32_t resultLength)
  10. {
  11.         return !!ReadFile(readPipeFile, resultBuffer, resultLength, nullptr, nullptr);
  12. }
复制代码
这两个函数非常简单,一目了然。

有了这些辅助函数,我们来看下一个命令。
  1. bool jlinkCommandReadEmulatorMemory(HANDLE readPipeFile, HANDLE writePipeFile, uint32_t address, uint32_t length, void* dataBuffer)
  2. {
  3.     uint8_t commandBuffer[9] =
  4.     {
  5.          0xfe,
  6.          static_cast<uint8_t>(address), static_cast<uint8_t>(address >> 8), static_cast<uint8_t>(address >> 16), static_cast<uint8_t>(address >> 24),
  7.          static_cast<uint8_t>(length), static_cast<uint8_t>(length >> 8), static_cast<uint8_t>(length >> 16), static_cast<uint8_t>(length >> 24),
  8.     };

  9.     return jlinkSendCommand(readPipeFile, writePipeFile, commandBuffer, sizeof(commandBuffer), dataBuffer, length);
  10. }
复制代码
这就是关键命令了,id=0xfe,读取jlink自身的内存区域,命令id之后是4个字节的地址,然后是4个字节的长度,都是le格式。
在使用这个命令的时候要注意,jlink有缓冲区大小限制,我们不能一次发送太多的数据到jlink,我们也不能一次读取太多的数据,这个缓冲区限制大小是64k,我们也可以使用下面两个函数获取这个值。
  1. uint32_t jlinkGetReadBufferSize(HANDLE deviceFile)
  2. {
  3.             uint32_t readBufferSize = 0;
  4.             jlinkDeviceControl(deviceFile, 0x220460, nullptr, 0, &readBufferSize, sizeof(readBufferSize));
  5.             return readBufferSize;
  6. }

  7. uint32_t jlinkGetWriteBufferSize(HANDLE deviceFile)
  8. {
  9.             uint32_t writeBufferSize = 0;
  10.             jlinkDeviceControl(deviceFile, 0x220464, nullptr, 0, &writeBufferSize, sizeof(writeBufferSize));
  11.             return writeBufferSize;
  12. }
复制代码
而jlinkDeviceControl这个函数只是一个简单的封装
  1. bool jlinkDeviceControl(HANDLE deviceFile, uint32_t controlCode, void* inputBuffer, uint32_t inputSize, void* outputBuffer, uint32_t outputSize, uint32_t* actualSize = nullptr)
  2. {
  3.             DWORD resultSize = 0;
  4.             if(!DeviceIoControl(deviceFile, controlCode, inputBuffer, sizeof(inputSize), outputBuffer, sizeof(outputSize), &resultSize, nullptr))
  5.                         return false;

  6.             if(actualSize)
  7.                         *actualSize = static_cast<uint32_t>(resultSize);

  8.             return true;
  9. }
复制代码
函数都全了,接下来就进入主题了。
首先我们知道jlink的bootloader占用的是0x08000000到0x08010000之间的64k内容,
其中从0x0800b700开始到0x0800c000的部分占据0x900个字节,jlink管他称为ots,大概是什么one time section的缩写?
这部分放的大约有3个东西,序列号,license,然后还有一段签名,这个贴的最后有部分ots的介绍。
这部分jlink并没有提供擦出功能,只能写入,你只能把某个位从1变成0,不能反过来(所以才叫one time?)
然后是从0x0800c000开始到0x0800c900同样也是0x900个字节的内容,这个部分jlink管他叫config data,
这部分jlink能够擦出,并且能用jlink自带的jlinkconfig.exe修改。
他里面主要放的是一些配置信息,比如昵称,是否打开虚拟串口,是否使用jlink给目标板供电什么的。

我们在读取bootloader的时候完全可以跳过ots和config部分,读取前面的0xb700个字节就可以了(实际上bootloader只有不到0x4000个字节)
  1.         uint8_t bootloader[0xb700] = {0};
  2.         jlinkCommandReadEmulatorMemory(readPipeFile, writePipeFile, 0x08000000, sizeof(bootloader), bootloader);
复制代码
就是这么简单,我们就拿到了bootloader。

但是不要着急,我们跳过了ots和config,这两个部分也挺重要的。
如果我们只是希望把挂掉的jlink救活,并且我们的jlink本身就是正版(正版会丢固件吗?我有个盗版丢了),那我们也需要把ots也读出来,
但是不要把ots发给其他人,ots里面有唯一的设备签名。
把坏掉的jlink擦除掉,然后把这个bootloader刷回去,通电,jlink能识别这个设备,即使这个设备里面只有bootloader,jlink会显示出bootloader的版本来。
大约是“J-Link V9 compiled Oct 12 2012 BTL”这样的。
然后我们可以使用jlinkconfig.exe从新写入固件,并不需要自己手动去jlink的dll里面导出固件再手动往里面刷。

如果我们想做个一摸一样的复制品(序列号也原样复制),那也把ots读出来。

如果我们想干坏事,批量生产一波,那么还需要了解一下ots这个东西。
ots有两个部分,从0xb700开始的0x100字节是一段数字签名,很不幸我这盗版jlink里面全是ff,正版用户可以看看这256个字节的数字签名。
jlink使用的是salt长度为4的rsa-pss算法来生成这段签名的。至于rsa-pss算法大家可以google一下。
签名的原始数据长度16个字节,前面4个字节是序列号,后面12个字节是stm32提供的设备唯一id。
rsa算法长度2048,很不幸现在没啥希望能算出他的私钥,所以大部分(全部?)的盗版这个签名部分都是0xff吧。
这段签名即使全是0xff也不影响jlink的功能,只是能用这个签名判断出是否是正版jlink,判断办法如下。
  1. bool jlinkCommandVerifySignature(HANDLE readPipeFile, HANDLE writePipeFile)
  2. {
  3.             uint8_t commandBuffer[] =
  4.             {
  5.                         0x18,
  6.                         0x01,
  7.                         0x01, 0x00, 0x00, 0x00,
  8.                         0x00,
  9.                         0x00,
  10.             };

  11.             int32_t isValid                                                                                                                = 0;
  12.             if(!jlinkSendCommand(readPipeFile, writePipeFile, commandBuffer, sizeof(commandBuffer), &isValid, sizeof(isValid)))
  13.                     return false;

  14.             return isValid > 0;
  15. }
复制代码
这个函数返回true的时候,那签名就是合法的,否则就是非法的,我大致看了看jlink的dll,似乎并没有使用这个判断?
签名这个0x100个字节我们先放一边(不放一边也没办法,2048位的rsa束手无策的)
rsa的e是常客0x10001,n在下面
  1. ROM:08011C28                 DCD 0x4FFF1729
  2. ROM:08011C2C                 DCD 0xAD96D829
  3. ROM:08011C30                 DCD 0xCD9F0C6A
  4. ROM:08011C34                 DCD 0x444F49FD
  5. ROM:08011C38                 DCD 3236562632
  6. ROM:08011C3C                 DCD 2651048264
  7. ROM:08011C40                 DCD 2156799988
  8. ROM:08011C44                 DCD 1002538269
  9. ROM:08011C48                 DCD 1414572176
  10. ROM:08011C4C                 DCD 728261039
  11. ROM:08011C50                 DCD 195953012
  12. ROM:08011C54                 DCD 4092138938
  13. ROM:08011C58                 DCD 3035786873
  14. ROM:08011C5C                 DCD 1754605398
  15. ROM:08011C60                 DCD 3394821355
  16. ROM:08011C64                 DCD 3852065468
  17. ROM:08011C68                 DCD 1379916164
  18. ROM:08011C6C                 DCD 2955657565
  19. ROM:08011C70                 DCD 3891065497
  20. ROM:08011C74                 DCD 372041464
  21. ROM:08011C78                 DCD 1715106254
  22. ROM:08011C7C                 DCD 3832064334
  23. ROM:08011C80                 DCD 254910677
  24. ROM:08011C84                 DCD 2322701057
  25. ROM:08011C88                 DCD 1330054993
  26. ROM:08011C8C                 DCD 3621432991
  27. ROM:08011C90                 DCD 0xE870EC79
  28. ROM:08011C94                 DCD 0x56C9D464
  29. ROM:08011C98                 DCD 0xA786970A
  30. ROM:08011C9C                 DCD 0x15A58D01
  31. ROM:08011CA0                 DCD 0x3481F0D4
  32. ROM:08011CA4                 DCD 0x371B4738
  33. ROM:08011CA8                 DCD 0xA1CF85E4
  34. ROM:08011CAC                 DCD 0xEFC0BA1B
  35. ROM:08011CB0                 DCD 0x512F550A
  36. ROM:08011CB4                 DCD 0xA2719983
  37. ROM:08011CB8                 DCD 0xCAFE135
  38. ROM:08011CBC                 DCD 0xC87FC0B1
  39. ROM:08011CC0                 DCD 0x35028880
  40. ROM:08011CC4                 DCD 0xAB5DE12
  41. ROM:08011CC8                 DCD 0xC791BF33
  42. ROM:08011CCC                 DCD 0xD38E90E4
  43. ROM:08011CD0                 DCD 0x93B510C5
  44. ROM:08011CD4                 DCD 0xC47DEB52
  45. ROM:08011CD8                 DCD 0xA359C991
  46. ROM:08011CDC                 DCD 0xB6C37DD8
  47. ROM:08011CE0                 DCD 0xDE7F258D
  48. ROM:08011CE4                 DCD 0xF5C6215B
  49. ROM:08011CE8                 DCD 0xC2DF133D
  50. ROM:08011CEC                 DCD 0x3B92601C
  51. ROM:08011CF0                 DCD 0x24B2416
  52. ROM:08011CF4                 DCD 0xB669CCD2
  53. ROM:08011CF8                 DCD 0x73477502
  54. ROM:08011CFC                 DCD 0x847F9D58
  55. ROM:08011D00                 DCD 0x69D5387F
  56. ROM:08011D04                 DCD 0x2CC6592A
  57. ROM:08011D08                 DCD 0x1BDCC656
  58. ROM:08011D0C                 DCD 0x5F4959FE
  59. ROM:08011D10                 DCD 0x745CB3ED
  60. ROM:08011D14                 DCD 0x60087B7D
  61. ROM:08011D18                 DCD 0xBC8436B4
  62. ROM:08011D1C                 DCD 0x6A0C76C7
  63. ROM:08011D20                 DCD 0x1B99A01F
  64. ROM:08011D24                 DCD 0xAE87F498
复制代码
其实知道了也没啥用。

接下来我们来看看序列号,他位于bf00,这个序列号用的地方有两个,一个自然就是序列号,另外一个是硬件版本,是的你没有看错。
硬件版本是用序列号来计算的,首先把序列号除以100000,得到的商再除以10,得到的余数如果大于等于8则取2,得到的就是子版本号。
比如我这个盗版设备,sn=59101308,他的硬件版本显示为9.10
sn先除以100000,商591,再除以10,余1,所以就是9.10
当序列号这个位置4个字节都是ff的时候,我们可以使用exec setsn=xxx来设置一个序列号,如果序列号已经有值了,这个命令就不能用了。

然后就是license,他从bf20开始,每个license占16个字节,他们就是普通的ascii字符串,包括结尾的0。
这个部分可以使用exec addfeature来添加license。

所以如果数字签名本身就是无效的话,那么ots部分我们可以完全不用管他,全部擦除成ff,然后用jlink的命令写入需要的值就可以了。
当然jlink也提供了两个命令来更新ots,这里介绍一个简单的,他只是更新bf00开始的0x100个字节,这个区域里面包括序列号和license。
  1. int32_t jlinkCommandWriteOneTimeSettings(HANDLE readPipeFile, HANDLE writePipeFile, void const* dataBuffer)
  2. {
  3.             uint8_t commandBuffer[0x10d] = {0x13};
  4.             uint32_t tempValue = crc32(0xffffffff, static_cast<uint8_t const*>(dataBuffer), 0x100) ^ 0xffffffff;
  5.             commandBuffer[0x101] = static_cast<uint8_t>(tempValue);
  6.             commandBuffer[0x102] = static_cast<uint8_t>(tempValue >> 8);
  7.             commandBuffer[0x103] = static_cast<uint8_t>(tempValue >> 16);
  8.             commandBuffer[0x104] = static_cast<uint8_t>(tempValue >> 24);
  9.             commandBuffer[0x105] = 0x49;
  10.             commandBuffer[0x106] = 0x44;
  11.             commandBuffer[0x107] = 0x53;
  12.             commandBuffer[0x108] = 0x45;
  13.             commandBuffer[0x109] = 0x47;
  14.             commandBuffer[0x10a] = 0x47;
  15.             commandBuffer[0x10b] = 0x45;
  16.             commandBuffer[0x10c] = 0x52;
  17.             memcpy(commandBuffer + 1, dataBuffer, 0x100);
  18.             if(!jlinkSendCommand(readPipeFile, writePipeFile, commandBuffer, sizeof(commandBuffer), &tempValue, sizeof(tempValue)))
  19.                     return -1;

  20.             return static_cast<int32_t>(tempValue);
  21. }
复制代码
发送过去的命令长度0x10d,第一个字节是命令id=0x13,接下里0x100个字节就是新的ots数据,然后是4个字节的crc32(根据crc32实现的默认初始值不同,我们可能需要调整0xffffffff这个值为0),接下来8个字节是个常量,他等于IDSEGGER的ascii码。
这个命令返回一个错误代码,如果成功写入了,返回的是0,否则返回一个负值。
注意,这个ots并不是我们想改成什么样子就能改成什么样子的,我们发送过去的0x100字节的新数据必须满足三个条件。
第一,如果原来的ots里面已经有一个非ffffffff的序列号了,那么我们的对应的序列号必须要和原始序列号相同,也就是说我们只有一次机会把序列号从0xffffffff改成其他的。
第二,我们发送过去的0x100数据里面的license不能是空的,具体的说就是0x100的ots数据的偏移量0x20这个地方不能是0
第三,我们只能把原始数据里面是1的位变成0,不能反过来。
如果我们发送过去的数据不满足这三个条件,jlink都会返回错误。
至于原来的bf00这部分的数据是什么,我们可以使用上面那个jlinkCommandReadEmulatorMemory函数来读取,或者可以使用下面这个专属命令。
  1. bool jlinkCommandReadOneTimeSettings(HANDLE readPipeFile, HANDLE writePipeFile, void* dataBuffer)
  2. {
  3.             uint8_t commandBuffer[1] = {0xe6};
  4.             return jlinkSendCommand(readPipeFile, writePipeFile, commandBuffer, sizeof(commandBuffer), dataBuffer, 0x100);
  5. }
复制代码
这个命令他只能读取固定的0x100个字节的数据(bf00到c000)

当然也有进阶的读取和更新全部0x900数据的命令,但是用处不大(我们盗版用户也没办法生成新的数字签名),这里就不多介绍了,感兴趣的朋友可以自己逆向一下jink的固件
当前版本的固件大约是这样的
  1. ROM:080114CC                 DCD EMU_CMD_01_VERSION+1
  2. ROM:080114D0                 DCD EMU_CMD_02_RESET_TRST+1
  3. ROM:080114D4                 DCD EMU_CMD_03_RESET_TARGET+1
  4. ROM:080114D8                 DCD EM_CMD_04_GET_INFO+1
  5. ROM:080114DC                 DCD EMU_CMD_05_SET_SPEED+1
  6. ROM:080114E0                 DCD EMU_CMD_06_UPDATE_FIRMWARE+1
  7. ROM:080114E4                 DCD EMU_CMD_07_GET_STATE+1
  8. ROM:080114E8                 DCD EMU_CMD_08_SET_KS_POWER+1
  9. ROM:080114EC                 DCD EMU_CMD_09_REGISTER_UNREGISTER+1
  10. ROM:080114F0                 DCD EMU_CMD_0A_INDICATORS+1
  11. ROM:080114F4                 DCD EMU_CMD_0B_PERMIT+1
  12. ROM:080114F8                 DCD EMU_CMD_0C_PCODE+1
  13. ROM:080114FC                 DCD EMU_CMD_0D_PROT_VERSION+1
  14. ROM:08011500                 DCD EMU_CMD_0E_SET_EMU_OPTION+1
  15. ROM:08011504                 DCD EMU_CMD_UNSUPPORTED+1
  16. ROM:08011508                 DCD EMU_CMD_UNSUPPORTED+1
  17. ROM:0801150C                 DCD EMU_CMD_11_MERGE_COMMANDS+1
  18. ROM:08011510                 DCD EMU_CMD_12_UPDATE_CONFIG_DATA_C000_C100+1
  19. ROM:08011514                 DCD EMU_CMD_13_UPDATE_CONFIG_DATA_B700_BF00+1
  20. ROM:08011518                 DCD EMU_CMD_UNSUPPORTED+1
  21. ROM:0801151C                 DCD EMU_CMD_15_SPI+1
  22. ROM:08011520                 DCD EMU_CMD_16_UPDATE_CONFIG_DATA+1
  23. ROM:08011524                 DCD EMU_CMD_17_HANDLE_C2+1
  24. ROM:08011528                 DCD EMU_CMD_18_+1
  25. ROM:0801152C                 DCD EMU_CMD_19_+1
  26. ROM:08011530                 DCD EMU_CMD_UNSUPPORTED+1
  27. ROM:08011534                 DCD EMU_CMD_UNSUPPORTED+1
  28. ROM:08011538                 DCD EMU_CMD_UNSUPPORTED+1
  29. ROM:0801153C                 DCD EMU_CMD_UNSUPPORTED+1
  30. ROM:08011540                 DCD EMU_CMD_UNSUPPORTED+1
  31. ROM:08011544                 DCD EMU_CMD_UNSUPPORTED+1
  32. ROM:08011548                 DCD EMU_CMD_UNSUPPORTED+1
  33. ROM:0801154C                 DCD EMU_CMD_C0_GET_SPEEDS+1
  34. ROM:08011550                 DCD EMU_CMD_C1_GET_HW_INFO+1
  35. ROM:08011554                 DCD EMU_CMD_C2_GET_COUNTERS+1
  36. ROM:08011558                 DCD EMU_CMD_C3_TEST_NET_SPEED+1
  37. ROM:0801155C                 DCD EMU_CMD_C4_CPU2_SET_CONFIG+1
  38. ROM:08011560                 DCD EMU_CMD_C5_CPU2_EXEC_CMD+1
  39. ROM:08011564                 DCD EMU_CMD_C6_GET_CPU2_CAPS+1
  40. ROM:08011568                 DCD EMU_CMD_C7_SELECT_IF+1
  41. ROM:0801156C                 DCD EMU_CMD_C8_HW_CLOCK+1
  42. ROM:08011570                 DCD EMU_CMD_C9_HW_TMS0+1
  43. ROM:08011574                 DCD EMU_CMD_CA_HW_TMS1+1
  44. ROM:08011578                 DCD EMU_CMD_CB_HW_DATA0+1
  45. ROM:0801157C                 DCD EMU_CMD_CC_HW_DATA1+1
  46. ROM:08011580                 DCD EMU_CMD_CD_HW_JTAG+1
  47. ROM:08011584                 DCD EMU_CMD_CE_HW_JTAG2+1
  48. ROM:08011588                 DCD EMU_CMD_CF_HW_JTAG3+1
  49. ROM:0801158C                 DCD EMU_CMD_D0_HW_RELEASE_RESET_STOP_EX+1
  50. ROM:08011590                 DCD EMU_CMD_D1_HW_RELEASE_RESET_STOP_TIMED+1
  51. ROM:08011594                 DCD EMU_CMD_UNSUPPORTED+1
  52. ROM:08011598                 DCD EMU_CMD_UNSUPPORTED+1
  53. ROM:0801159C                 DCD EMU_CMD_D4_GET_MAX_MEM_BLOCK+1
  54. ROM:080115A0                 DCD EMU_CMD_D5_HW_JTAG_WRITE+1
  55. ROM:080115A4                 DCD EMU_CMD_D6_HW_JTAG_GET_RESULT+1
  56. ROM:080115A8                 DCD EMU_CMD_UNSUPPORTED+1
  57. ROM:080115AC                 DCD EMU_CMD_UNSUPPORTED+1
  58. ROM:080115B0                 DCD EMU_CMD_UNSUPPORTED+1
  59. ROM:080115B4                 DCD EMU_CMD_DA_HW_TCK0+1
  60. ROM:080115B8                 DCD EMU_CMD_DB_HW_TCK1+1
  61. ROM:080115BC                 DCD EMU_CMD_DC_HW_RESET0+1
  62. ROM:080115C0                 DCD EMU_CMD_DD_HW_RESET1+1
  63. ROM:080115C4                 DCD EMU_CMD_DE_HW_TRST0+1
  64. ROM:080115C8                 DCD EMU_CMD_DF_HW_TRST1+1
  65. ROM:080115CC                 DCD EMU_CMD_E0_FINE_WRITE_READ+1
  66. ROM:080115D0                 DCD EMU_CMD_E1_CDC_EXEC+1
  67. ROM:080115D4                 DCD EMU_CMD_UNSUPPORTED+1
  68. ROM:080115D8                 DCD EMU_CMD_UNSUPPORTED+1
  69. ROM:080115DC                 DCD EMU_CMD_UNSUPPORTED+1
  70. ROM:080115E0                 DCD EMU_CMD_E5_GET_CPU2_CAPS_DLL_VERSION+1
  71. ROM:080115E4                 DCD EMU_CMD_E6_READ_CONFIG_DATA_BF00_C000+1
  72. ROM:080115E8                 DCD EMU_CMD_E7_SYNC_KS_POWER_FROM_CONFIG_DATA+1
  73. ROM:080115EC                 DCD EMU_CMD_E8_GET_CAPS+1
  74. ROM:080115F0                 DCD EMU_CMD_E9_GET_CPU_CAPS+1
  75. ROM:080115F4                 DCD EMU_CMD_EA_EXEC_CPU_CMD+1
  76. ROM:080115F8                 DCD EMU_CMD_EB_SWO+1
  77. ROM:080115FC                 DCD EMU_CMD_UNSUPPORTED+1
  78. ROM:08011600                 DCD EMU_CMD_ED_GET_CAPS_EX+1
  79. ROM:08011604                 DCD EMU_CMD_UNSUPPORTED+1
  80. ROM:08011608                 DCD EMU_CMD_UNSUPPORTED+1
  81. ROM:0801160C                 DCD EMU_CMD_F0_GET_HW_VERSION+1
  82. ROM:08011610                 DCD EMU_CMD_F1_WRITE_DCC+1
  83. ROM:08011614                 DCD EMU_CMD_F2_READ_CONFIG_C000_C100+1
  84. ROM:08011618                 DCD EMU_CMD_F3_WRITE_CONFIG_DUMMY+1
  85. ROM:0801161C                 DCD EMU_CMD_F4_WRITE_MEM+1
  86. ROM:08011620                 DCD EMU_CMD_F5_READ_MEM+1
  87. ROM:08011624                 DCD EMU_CMD_F6_MEASURE_RTCK_REACT+1
  88. ROM:08011628                 DCD EMU_CMD_F7_WRITE_MEM_ARM79+1
  89. ROM:0801162C                 DCD EMU_CMD_F8_READ_MEM_ARM79+1
  90. ROM:08011630                 DCD EMU_CMD_UNSUPPORTED+1
  91. ROM:08011634                 DCD EMU_CMD_FA_READ_DCC+1
  92. ROM:08011638                 DCD WRITE_DCC_EX+1
  93. ROM:0801163C                 DCD EMU_CMD_UNSUPPORTED+1
  94. ROM:08011640                 DCD EMU_CMD_UNSUPPORTED+1
  95. ROM:08011644                 DCD EMU_CMD_FE_READ_EMU_MEM+1
  96. ROM:08011648                 DCD EMU_CMD_UNSUPPORTED+1
复制代码
有了这些信息,大家可以救活自己死掉的jlink,也可以自己做一个精简版的jlink(光是bootloader也许不够?还需要原理图?)
顺便多一句,网上能搜索到那个原理图根我手上的这个盗版有两个地方不一样,lm324那里,我这个盗版运放2是个5v的电压跟随器模式,运放1是个同步放大器模式(外围电阻并没焊接),
从固件里面看可以通过在启动的时候将PC13拉低来启用运放1,我不知道正版这个部分是怎么样子的。


接下来我们来看一个麻烦一点的办法,这个有风险要拆机,我的bootloader就是用这个办法弄出来的。
这也是论坛上各位大牛早就研究过的办法,就是写一段木马进去把bootloader用串口的办法发送出来。
这里我们使用一个相对安全的办法来dump出bootloader。
我们在jlink的固件里面找到一段不使用代码,插入我们的一段小程序进去,然后把启动向量指向我们的小程序,
这段小程序在上电的时候先通过读取某gpio管教的电平高低来决定继续执行还是跳转到原始jlink的启动向量。
这样一来,我们的这段小程序不会影响到jlink本身的功能,jlink可以正常使用,只有在上电的时候我们短接某个管脚,才会进入dump模式。
只要我们的程序在判读管脚高低电平的时候没有出错,即使接下里的代码里面有问题,也没关系,因为jlink是可以正常使用的,我们可以修改再来过。

因为我们的代码要和jlink的代码共存,所以,我们需要使用汇编语言来生成这段代码,这样能做到比较短小,毕竟jlink里面废代码并不多。

首先我们需要找到“废代码”的位置,这个挺容易的,中断表里面通常有很多中断都是不使用的,对应的中断处理函数的代码都是一个死循环。
我们可以直接覆盖掉这些中断处理函数,因为他们本身就不会被触发,为了安全我们可以保留一个这样的函数,并把其他的中断向量都指向到这个函数上,这里我偷懒并没有这样做。

那么这段废代吗在什么地方呢?就在0802cff0的地方,我们可以看到这里都是一堆的jump指令,好了,覆盖他们
                                    ldr                r0, =0x40023830
                                    ldr                r1, [r0]
                                    orr                r1, r1, #7
                                    str                r1, [r0]                                // enable GPIOA, GPIOB, GPIOC

                                    ldr                r5, =0x40020400
                                    ldr                r0, [r5]
                                    bic                r0, r0, #0xf00000
                                    orr                r0, r0, #0x200000
                                    str                r0, [r5]                                // PB10 = af, PB11 = input

                                    add                r2, r5, #0x10                        // read PB11
                                    ldr                r0, [r2]
                                    tst                r0, #0x800                                // if PB11 is high then jmp to jlink
                                    bne                finished

                                    add                r4, r5, #0x24
                                    ldr                r0, [r4]
                                    bic                r0, r0, #0xf00
                                    orr                r0, r0, #0x700                        // sete PB10 as af7 = USART3_TX
                                    str                r0, [r4]

                                    ldr                r0, =0x40023840                        // enable USART3 clock
                                    ldr                r1, [r0]
                                    orr                r1, r1, #0x40800                // enable USART3 + WWDG
                                    str                r1, [r0]

                                    ldr                r4, =0x40004800                        // r4 = USART_SR
                                    add                r5, r4, 0x0c                        // r5 = USART_CR
                                    ldr                r0, [r5]
                                    bic                r0, #0x2000                                // UE = 0, disable USART first
                                    str                r0, [r5]

                                    mov                r0, #0x0008                                // TE = 1, enable tx
                                    str                r0, [r5]
                                    add                r3, r4, #0x10                        // r3 = USART_CR2
                                    mov                r0, #0
                                    str                r0, [r3]

                                    add                r3, r4, #0x08                        // r3 = USART_BRR
                                    mov                r0, #0x104                                // 30Mhz / 115200 / 16 = 16.25
                                    str                r0, [r3]

                                    ldr                r0, [r5]
                                    orr                r0, #0x2000                                // UE = 1, enable USART
                                    str                r0, [r5]

                                    add                r5, r4, #4                                // r5 = USART_DR

                                    ldr                r6, =0x40002c00                        // r6 = WWDG_CR
                                    mov                r7, #0x7f

                    dump_start:
                                    ldr                r1, =0x08000000                        // r1 = current address
                                   mov                r2, #0x10000                        // r2 = left count
               
                    wait_txe:
                                    ldr                r0, [r4]
                                    tst                r0, #0x80                                // test TXE
                                    beq                wait_txe

                                    str                r7, [r6]                                // reload watchdog
                                    ldrb              r0, [r1], #1                        // load current byte and output to USART3
                                    str                r0, [r5]

                    wait_tc:
                                    ldr                r0, [r4]
                                    tst                r0, #0x40                                // wait TC
                                    beq                wait_tc

                                    subs               r2, r2, 1
                                    bne                wait_txe

                                    b                   dump_start

                     finished:
                                    ldr                pc, =0x0802cf61    // jump to jlink's reset handler

代码简单直接,就不多描述了,我是用的时arm-gcc编译器,大家也许需要做做移植工作才能在别的编译器下面编译。
这里面也许唯一需要说的就是串口的波特率计算,怎么知道当前的时钟频率究竟是多少。
当然也可以不管三七二十一初始化一趟RCC,不过这样会增加许多的代码量,
我这里比较偷懒,首先假定时钟频率是16MHz,然后按照115200的波特率算出一个值来,
接着让它开始dump,然后接入一个能自动分析波特率的逻辑分析仪,逻辑分析仪能汇报一个不太准确的波特率,
没关系,用这个不太准确的波特率回推出一个不太准确的时钟频率,我这里算出来是个30.13MHz,那么显然实际的时钟就是30MHz
然后在修改成30MHz的参数实际的跑一下,顺利拿到bootloader。

拿到bootloader以后,我转为逆向jlink固件,才发现有更简单的办法读取bootloader,于是这个代码也就用处不大了。
==================================================================================
题外话,也许大家有兴趣逆向jlink的固件?我这里提供一些简单的经验。
jlink使用的时他们自己家的实时操作系统embOS作为底层,这个embOS有源代码,但是需要买,我肯定买不起,不过好在他们家提供试用版。
大家可以下载试用版然后用ida打开,即使没有源代码,但是也有头文件,这里有几个结构定义,然后还有库文件,虽然库文件也是只能分析汇编,但是库文件能看到函数名字!
这样大家能分析出很多库代码,能将上层逻辑和操作系统代码剥离开,清晰不少。

然后还有一个,这个固件里面的初始化数据经过压缩,也不知道是谁家的编译器(ti家的编译器有这个压缩功能,不过我没详细看过),大家还需要一份代码来解压缩。
  1. uint8_t const* in8 = 0x0802D2BC;
  2. uint8_t* out8 = 0x20000008;
  3. while(out8 < 0x20000008 + 0x814)
  4. {
  5.     uint32_t c  = *in8 ++;
  6.     uint32_t a = c & 3;
  7.     if(!a)
  8.         a = 3 + static_cast<uint32_t>(*in8 ++);

  9.     uint32_t b = c >> 4;
  10.     if(b == 0x0f)
  11.         b = 0xf + static_cast<uint32_t>(*in8 ++);

  12.     while(-- a)
  13.         *out8 ++ = *in8 ++;

  14.     if(b)
  15.     {
  16.         uint32_t e = *in8 ++;
  17.         uint32_t d = (c >> 2) & 0x03;
  18.         if(d == 3)
  19.             d = *in8 ++;

  20.         d = (d << 8) + e;
  21.         uint8_t* back8 = out8 - d;
  22.         for(uint32_t j = 0; j < b + 2; j ++)
  23.             *out8 ++ = *back8 ++;
  24.         }
  25.     }
复制代码
也很简单的,当前这个版本,压缩之前的代码在0802D2BC,长度0x668,解开到20000008,长度0x814
解开的数据可以用ida再加载进去。方便分析。

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

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2016-6-25 23:33:55 | 显示全部楼层
强贴 学习

出0入0汤圆

发表于 2016-6-25 23:35:00 | 显示全部楼层
这个也行啊,牛.

出0入134汤圆

发表于 2016-6-25 23:43:15 | 显示全部楼层
好生猛,前排围观

出100入101汤圆

发表于 2016-6-25 23:45:12 | 显示全部楼层
技术大牛!

出0入12汤圆

发表于 2016-6-25 23:55:54 | 显示全部楼层
厉害

出0入22汤圆

发表于 2016-6-26 00:02:23 | 显示全部楼层
终于有大神出现了,以前的讨论大多都是隐晦不谈方法,这个必须顶啊,seeger要哭了,某link要更加白菜价了

出0入0汤圆

发表于 2016-6-26 00:23:02 | 显示全部楼层
还是FE指令

出0入0汤圆

发表于 2016-6-26 00:47:09 来自手机 | 显示全部楼层
其实和指令是一样的。改天试试写个软件试试你的方法

出0入0汤圆

发表于 2016-6-26 01:03:44 来自手机 | 显示全部楼层
另,bf08后面还有4个字节,也是D版没有的^_^

出0入0汤圆

发表于 2016-6-26 01:07:10 | 显示全部楼层
楼主高手

出0入0汤圆

发表于 2016-6-26 07:06:59 | 显示全部楼层
这个太强了。压缩数据段不需要编译器参与,可以编译出来加个壳。需要知道数据段的位置和startup的时候初始化一下就好了。

出0入0汤圆

发表于 2016-6-26 07:07:05 来自手机 | 显示全部楼层
楼主牛人

出0入0汤圆

发表于 2016-6-26 07:08:29 | 显示全部楼层
牛人啊,不过对高手来说这点信息足够了,对我等菜鸟来说,还是只能看看,不过还是感谢楼主的分享

出200入0汤圆

发表于 2016-6-26 07:39:18 来自手机 | 显示全部楼层
高手,膜拜

出0入0汤圆

发表于 2016-6-26 07:50:41 | 显示全部楼层
牛人  分析透彻

出0入0汤圆

发表于 2016-6-26 07:55:41 | 显示全部楼层
膜拜  高人的技术贴

出0入0汤圆

发表于 2016-6-26 07:56:29 来自手机 | 显示全部楼层
Thumbs up!

出0入0汤圆

发表于 2016-6-26 08:03:34 来自手机 | 显示全部楼层
stlink  V21的bootloader怎么弄?

出0入0汤圆

发表于 2016-6-26 08:04:32 | 显示全部楼层
霸气侧漏 发表于 2016-6-26 08:03
stlink  V21的bootloader怎么弄?

转到JLINK版本,同样方法弄。

出0入0汤圆

发表于 2016-6-26 08:06:48 来自手机 | 显示全部楼层
boboo 发表于 2016-6-26 08:04
转到JLINK版本,同样方法弄。

你弄过???

出0入0汤圆

发表于 2016-6-26 08:15:13 | 显示全部楼层

V2成功提取。
V2-1没有硬件,无解

出0入0汤圆

发表于 2016-6-26 08:15:19 | 显示全部楼层
好牛掰的分析,看来ARM在代码中做了那么多重的保护确实是有原因的。

出0入0汤圆

发表于 2016-6-26 08:18:38 | 显示全部楼层
这也太牛了,这得修炼多久啊;看都很累,赞一个

出0入12汤圆

发表于 2016-6-26 08:26:03 | 显示全部楼层
牛啊,step by step 啊。

出0入8汤圆

发表于 2016-6-26 08:28:45 来自手机 | 显示全部楼层
那玩意不叫压缩,就是简单的把相同的数据放一起
用的就是mdk编译器

出0入0汤圆

发表于 2016-6-26 09:13:25 来自手机 | 显示全部楼层
牛人,膜拜

出0入0汤圆

发表于 2016-6-26 09:22:44 来自手机 | 显示全部楼层
楼主玩芯片应该也非常溜了

出0入0汤圆

发表于 2016-6-26 09:23:08 | 显示全部楼层

牛人,膜拜.  

出0入0汤圆

发表于 2016-6-26 09:30:04 来自手机 | 显示全部楼层
牛人,膜拜

出0入0汤圆

发表于 2016-6-26 09:53:24 | 显示全部楼层
厉害,佩服。

出0入0汤圆

发表于 2016-6-26 10:07:54 | 显示全部楼层
有技术含量的贴。。。

出0入4汤圆

发表于 2016-6-26 10:14:25 | 显示全部楼层
这是我见过最精彩的JLINK分析贴。

出0入0汤圆

发表于 2016-6-26 10:21:26 | 显示全部楼层
学习,谢谢!!!

出0入0汤圆

发表于 2016-6-26 10:30:39 来自手机 | 显示全部楼层
真是太牛了,当时大家都是谈用木马,思路和你说的也一样,没想到你还真做到了,当时不知道谁说代码有检验的,看来并没有啊,其实代码如果是有检验就不能用简单的木马来做了,segger在这里不知道是有意还是无意留个漏洞

出0入0汤圆

发表于 2016-6-26 10:56:26 | 显示全部楼层
这个技术贴必须收藏

出0入0汤圆

发表于 2016-6-26 11:09:29 来自手机 | 显示全部楼层
谢谢楼主分享

出0入0汤圆

发表于 2016-6-26 11:10:02 | 显示全部楼层
虽然没看明白,还是mark一把,呵呵。

出0入0汤圆

发表于 2016-6-26 11:14:25 | 显示全部楼层
楼主大牛啊

出0入0汤圆

发表于 2016-6-26 11:30:55 | 显示全部楼层
好厉害了

出0入0汤圆

发表于 2016-6-26 11:45:41 | 显示全部楼层
不知道SEGGER公司看到这帖子会是什么心情

出0入0汤圆

发表于 2016-6-26 11:57:14 来自手机 | 显示全部楼层
source.ant 发表于 2016-6-26 11:45
不知道SEGGER公司看到这帖子会是什么心情

9卖了这么多年,快退市了,公布了也影响不大。V10升级了,更难

出0入0汤圆

发表于 2016-6-26 12:20:40 来自手机 | 显示全部楼层
太强悍了

出0入0汤圆

发表于 2016-6-26 12:25:14 | 显示全部楼层
这个研究得很深入啊!

出0入34汤圆

发表于 2016-6-26 13:36:08 | 显示全部楼层
不得不说,真心的佩服了!...

出0入0汤圆

发表于 2016-6-26 14:21:17 | 显示全部楼层
虽然看不懂,不过还是收藏一下。

出0入0汤圆

发表于 2016-6-26 14:37:18 | 显示全部楼层
花这么多精力来研究,强!

出0入0汤圆

发表于 2016-6-26 14:44:51 | 显示全部楼层
不明觉厉!

出0入0汤圆

发表于 2016-6-26 14:55:26 | 显示全部楼层
不明觉厉

出0入0汤圆

发表于 2016-6-26 15:02:32 | 显示全部楼层
看样子V10也要火了,

出0入0汤圆

发表于 2016-6-26 15:06:08 | 显示全部楼层
精彩,估计SEGGER要堵封了。

出0入0汤圆

发表于 2016-6-26 15:31:24 来自手机 | 显示全部楼层
楼主太厉害了,虽然看不太懂!

出0入0汤圆

发表于 2016-6-26 16:11:44 | 显示全部楼层
強人,收藏 ,謝謝.

出0入0汤圆

发表于 2016-6-26 16:22:08 | 显示全部楼层
厉害,学习中。。

出15入9汤圆

发表于 2016-6-26 16:31:20 | 显示全部楼层
嘿,自从掉过固件之后,以后都用ST-LINK了。。

出0入0汤圆

发表于 2016-6-26 17:36:58 | 显示全部楼层
不错不错,已经很接近我几年前的研究了。当然也有一些小错误,无伤大雅。

出0入0汤圆

发表于 2016-6-26 17:52:33 | 显示全部楼层
楼主是高手,技术杠杠的。

出0入0汤圆

发表于 2016-6-26 17:58:18 来自手机 | 显示全部楼层
太精彩啦,收藏一下

出0入0汤圆

发表于 2016-6-26 18:15:38 来自手机 | 显示全部楼层
taoist 发表于 2016-6-26 17:36
不错不错,已经很接近我几年前的研究了。当然也有一些小错误,无伤大雅。 ...

几个意思,少年

出0入0汤圆

发表于 2016-6-26 18:23:03 | 显示全部楼层
佩服楼主!!!!!

出0入0汤圆

发表于 2016-6-26 18:41:34 | 显示全部楼层
技术大牛,佩服

出0入0汤圆

发表于 2016-6-26 18:50:26 | 显示全部楼层
需要3个月的时间才能消化

出0入0汤圆

发表于 2016-6-26 18:56:23 来自手机 | 显示全部楼层
牛人,很仰慕

出0入0汤圆

发表于 2016-6-26 19:04:23 来自手机 | 显示全部楼层
霸气侧漏 发表于 2016-6-26 18:15
几个意思,少年

哈哈,居然问Segger国内第一牛人几个意思^_^

出0入0汤圆

发表于 2016-6-26 19:13:01 来自手机 | 显示全部楼层
佩服,研究透彻了

出0入0汤圆

发表于 2016-6-26 21:52:37 | 显示全部楼层
分析透彻,学习

出0入0汤圆

发表于 2016-6-26 22:35:17 来自手机 | 显示全部楼层
佩服,学习了

出0入0汤圆

发表于 2016-6-26 22:51:11 | 显示全部楼层
Bootloader在哪呢??

出0入0汤圆

发表于 2016-6-26 22:58:47 来自手机 | 显示全部楼层
yondyanyu 发表于 2016-6-26 22:51
Bootloader在哪呢??

都这么清楚了,自己在动动手吧。

出0入0汤圆

发表于 2016-6-26 23:09:11 | 显示全部楼层
Mark and 顶!!!!!!!!!

出0入0汤圆

发表于 2016-6-26 23:14:08 | 显示全部楼层
boboo 发表于 2016-6-26 19:04
哈哈,居然问Segger国内第一牛人几个意思^_^

我也差点想问这个问题

出0入0汤圆

发表于 2016-6-26 23:28:49 | 显示全部楼层
我去,这也可以?信息量太大了,要好好消化一下。

出0入0汤圆

发表于 2016-6-26 23:50:26 来自手机 | 显示全部楼层
boboo 发表于 2016-6-26 19:04
哈哈,居然问Segger国内第一牛人几个意思^_^

你是几个意思

出0入0汤圆

发表于 2016-6-26 23:50:49 来自手机 | 显示全部楼层
iwinstone 发表于 2016-6-26 23:14
我也差点想问这个问题

哈哈,让你们笑话了,

出0入0汤圆

发表于 2016-6-27 00:44:21 来自手机 | 显示全部楼层
mark,好好学习

出0入0汤圆

发表于 2016-6-27 07:39:22 | 显示全部楼层
不用担心V9掉固件了,有空弄弄看。

出0入0汤圆

发表于 2016-6-27 08:04:35 | 显示全部楼层
学习学习了,主要是看方法。

出0入0汤圆

发表于 2016-6-27 08:17:01 | 显示全部楼层
膜拜  高人

出0入0汤圆

发表于 2016-6-27 08:54:33 | 显示全部楼层
厉害了,高人都藏得这么深

出0入0汤圆

发表于 2016-6-27 08:55:35 | 显示全部楼层
楼主高人,还在啃着v7呢

出0入0汤圆

发表于 2016-6-27 09:00:14 | 显示全部楼层
不明觉厉!!!

出0入0汤圆

发表于 2016-6-27 09:08:26 | 显示全部楼层
这个支持。

出0入0汤圆

发表于 2016-6-27 09:15:10 | 显示全部楼层
强贴 学习

出0入0汤圆

发表于 2016-6-27 09:25:47 | 显示全部楼层
真正的技术大牛啊

出0入0汤圆

发表于 2016-6-27 09:27:05 | 显示全部楼层
楼主,高人, 这个思路很好,又学到了一招!

出0入0汤圆

发表于 2016-6-27 09:27:16 | 显示全部楼层
强贴,支持一下

出100入18汤圆

发表于 2016-6-27 09:28:16 | 显示全部楼层
太牛了,不得不打赏一下!

出0入0汤圆

发表于 2016-6-27 09:28:46 来自手机 | 显示全部楼层
这个够详细
头像被屏蔽

出0入0汤圆

发表于 2016-6-27 09:31:06 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

发表于 2016-6-27 09:55:43 | 显示全部楼层
myxiaonia 发表于 2016-6-26 10:30
真是太牛了,当时大家都是谈用木马,思路和你说的也一样,没想到你还真做到了,当时不知道谁说代码有检验的 ...

如果有校验,似乎只能通过反汇编那个DLL里的固件才能找到用什么校验算法和在什么位置校验了, 不过楼主都已经反汇编了,估计也不是事,只是工作量会很大。

出0入0汤圆

发表于 2016-6-27 09:57:23 | 显示全部楼层


你搜搜这位taoist前辈的贴吧,人家早就搞定V10了。。。 各种LINK版本似乎从来不用样品就能破出来。

出0入0汤圆

发表于 2016-6-27 10:03:36 | 显示全部楼层
只要我们的程序在判读管脚高低电平的时候没有出错,即使接下里的代码里面有问题,也没关系,因为jlink是可以正常使用的,我们可以修改再来过



多次反复升级固件如何做的,有手工升级命令?还是手工能改固件版本号让软件检测到新版本升级?

出0入0汤圆

发表于 2016-6-27 10:10:09 来自手机 | 显示全部楼层
之前在另个论坛看到有说木马吐boot成功但是只能烧回本芯片不能烧其他芯片 有id号

出0入0汤圆

发表于 2016-6-27 11:29:47 | 显示全部楼层
神一样的膜拜你~

出0入0汤圆

发表于 2016-6-27 14:11:47 | 显示全部楼层
牛人,帮顶,我只能学习一下啊,有没有搞出来一个能用的bootloader想拿来用用,V9变砖了想重刷一下。

出0入0汤圆

发表于 2016-6-27 14:50:07 | 显示全部楼层
霸气侧漏 发表于 2016-6-26 23:50
哈哈,让你们笑话了,

其实我也不认识这哥们,不过看后面的回复,应该三一个对Segger研究很深的人,论坛卧虎藏龙,到处三人才阿

出0入0汤圆

发表于 2016-6-28 11:52:08 | 显示全部楼层
牛人,,虽然看不蛮懂,,

出0入0汤圆

发表于 2016-6-28 12:56:01 来自手机 | 显示全部楼层
看不懂,做过伸手党,那位大侠把bootloader的bin文件贴出来吧

出0入0汤圆

发表于 2016-6-28 13:41:11 | 显示全部楼层
分析得透彻,收藏了!

出0入0汤圆

发表于 2016-6-28 18:27:42 | 显示全部楼层

我之前也做了一个,直接读出boot

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

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

本版积分规则

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

GMT+8, 2024-4-26 08:17

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

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