yjmwxwx
发表于 2021-1-27 10:38:00
分立元件 发表于 2021-1-27 10:24
我花的都记不清楚了,几万了至少了,十几年了
你花的可真多,玩电子真是无底洞啊,我花了3000多一分钱也没在电子和程序方面挣过,反而游戏代练挣过300元。:lol
JuncoJet
发表于 2021-1-27 10:44:06
yjmwxwx 发表于 2021-1-27 09:57
这个就是FW_1_10a改的,和刷这个新固件应该一样,变砖头好像清空FM25W256的固件,清空外部FRAM就能刷回原 ...
铁电存储器?比较少见啊
yjmwxwx
发表于 2021-1-27 10:45:58
iffi123 发表于 2021-1-27 10:37
问题是你懂的怎么清空,不见得别人也懂啊,,,, 这脑子,,,,
所以刚才我才说最好自己已经验 ...
作者好像有清空FRAM的固件
yjmwxwx
发表于 2021-1-27 10:48:46
JuncoJet 发表于 2021-1-27 10:44
铁电存储器?比较少见啊
电路我不懂,电路图作者资料里面有
https://yadi.sk/d/4ZgsrswxYClG1Q
yjmwxwx
发表于 2021-1-27 15:19:54
修改的过程
https://bbs.pediy.com/thread-265660.htm
分立元件
发表于 2021-1-27 22:58:01
要是有钱肯定要支援一些设备给你!
yjmwxwx
发表于 2021-1-28 00:26:26
分立元件 发表于 2021-1-27 22:58
要是有钱肯定要支援一些设备给你!
虽然你帮不上我,但是还是谢谢了。
我这人性格很怪的,让我帮别人可以,别人想帮我就不用想了我肯定不会接受。
我现在主要种地是主业,业余有钱就玩玩没钱就算了,感觉我和钱没缘,只要能挣钱的东西让我干都不行,也就种地还凑合。
iffi123
发表于 2021-1-28 08:53:30
本帖最后由 iffi123 于 2021-1-28 08:59 编辑
从你的分析上, 作者应该是遵循了标准的C开发习惯,即在显示字库里,字母/数字/符号是按照ascii的顺序排列的,比如为了显示这一串提示,可以用
unsigned charaa[]="THE DEVICE SOFTWARE..."来定义; 实际存储的是该字母的ascii码(在字库里的索引号), 反编译软件能识别bin的程序区和数据区(只读), 如果数据区存在连续的数据按ascii码的内容不是控制符,就可以当字母数字显示出来(这就像在电脑用记事本打开exe文件,仍然可以看到程序里的提示文本信息), 所以你能直接搜索到屏幕提示的字符串。
如果按照很多人的习惯,字库只包含A-Z, a-z, 0-9再加上少量的符号的话, 那么字母在字库的索引号不再按照ascii顺序,比如字母A的索引号可能用00代替,B用01,反编译软件就无法识别这些数据是字母, 你也就难以找到注册画面所在的程序位置, 我觉的这是作者的疏忽。
咸鱼有专门的收钱注册的,本身不卖机,我觉的这种很可能是破解了(不是向作者购买),找到算号的方法或者其它途径
yjmwxwx
发表于 2021-1-28 09:33:48
本帖最后由 yjmwxwx 于 2021-1-28 09:45 编辑
iffi123 发表于 2021-1-28 08:53
从你的分析上, 作者应该是遵循了标准的C开发习惯,即在显示字库里,字母/数字/符号是按照ascii的顺序排列 ...
要写算号器也不难,就是我C语言不怎么会用
看懂下面这两个函数就能写算号器了
这个是显示ID号的,只是把ID号码简单移位来显示
seg000:080198B0 LDR R0, =unk_2001AFC8 ; 96位ID储存地址
seg000:080198B2 LDR R1, =a04x04x04x04x04 ; "%04X-%04X-%04X-%04X-%04X-%04X"
seg000:080198B4 PUSH.W {R4-R10,LR}
seg000:080198B8 LDRB R2,
seg000:080198BA SUB SP, SP, #0x10
seg000:080198BC LDRB R5,
seg000:080198BE LDRB R3,
seg000:080198C0 LDRB R4,
seg000:080198C2 ADD.W R2, R2, R5,LSL#8
seg000:080198C6 LDRB R7,
seg000:080198C8 ADD.W R3, R3, R4,LSL#8
seg000:080198CC LDRB R5,
seg000:080198CE LDRB R6,
seg000:080198D0 SXTH R2, R2
seg000:080198D2 LDRB R4,
seg000:080198D4 ADD.W R7, R7, R5,LSL#8
seg000:080198D8 LDRB R5,
seg000:080198DA SXTH R3, R3
seg000:080198DC LDRB.W LR,
seg000:080198E0 ADD.W R6, R6, R4,LSL#8
seg000:080198E4 LDRB R4,
seg000:080198E6 SXTH R7, R7
seg000:080198E8 LDRB R0,
seg000:080198EA ADD.W R5, R5, LR,LSL#8
seg000:080198EE SXTH R6, R6
seg000:080198F0 STR R7,
seg000:080198F2 ADD.W R4, R4, R0,LSL#8
seg000:080198F6 LDR R0, =unk_20006190
seg000:080198F8 SXTH R5, R5
seg000:080198FA STR R6,
seg000:080198FC SXTH R4, R4
seg000:080198FE STR R5,
seg000:08019900 STR R4,
下面这个是从ID号计算密码的,这个注释写的有点差劲。。
seg000:0800D748 ; ID
seg000:0800D748 ; r0=ID地址0x2001AFC8
seg000:0800D748
seg000:0800D748 sub_800D748 ; CODE XREF: sub_8019AF8+2E↓p
seg000:0800D748 PUSH {R4-R6}
seg000:0800D74A MOVS R2, #0; R2=0
seg000:0800D74C SUBS R3, R0, #1 ; R3=R0-1
seg000:0800D74E ADD.W R5, R0, #0xB ; R5=R0+0X0B
seg000:0800D752
seg000:0800D752 loc_800D752 ; CODE XREF: sub_800D748+12↓j
seg000:0800D752 LDRSB.W R4, ! ; 读8位ID
seg000:0800D756 CMP R5, R3
seg000:0800D758 ADD R2, R4; ID累加
seg000:0800D75A BNE loc_800D752 ; 读8位ID
seg000:0800D75C LDRSB.W R3, ; 读ID 最低8位
seg000:0800D760 UBFX.W R2, R2, #0, #0xA ; 提取10位
seg000:0800D764 LDRSB.W R4, ; 读ID最高8位
seg000:0800D768 SUBS R0, R1, #1 ; R0=0X2001AF54-1
seg000:0800D76A LDR R6, =unk_2001AE88
seg000:0800D76C ADDS R1, #7; R1=0X200001AF54 + 7
seg000:0800D76E ADD R3, R4; ID最高8位+ID最低8位
seg000:0800D770 LDR R5, =0x20001AC8
seg000:0800D772 LDR R4, =unk_2001AE8C
seg000:0800D774 ADD R3, R2; 最高8位+最低8位结果+ID累加提取的10位
seg000:0800D776 STR R2, ; ID累加提取的10位
seg000:0800D776 ; 保存到
seg000:0800D776 ; 0x2001AE88
seg000:0800D778 UBFX.W R3, R3, #0, #0xA ; ID最高8位
seg000:0800D778 ; 加
seg000:0800D778 ; ID最低8位
seg000:0800D778 ; 加
seg000:0800D778 ; ID累加结果提取的10位
seg000:0800D778 ; 的结果
seg000:0800D778 ; 提取10位
seg000:0800D77C STR R3, ; 保存到
seg000:0800D77C ; 0x2001AE8C
seg000:0800D77E
seg000:0800D77E loc_800D77E ; CODE XREF: sub_800D748+46↓j
seg000:0800D77E LDR.W R4, ;
seg000:0800D77E ; r5=0x20001AC8
seg000:0800D77E ; 加
seg000:0800D77E ; r3
seg000:0800D77E ; 地址的数据放到
seg000:0800D77E ; R4
seg000:0800D782 ADD R3, R2; r3
seg000:0800D782 ; +
seg000:0800D782 ; ID蕾姐结果提取10位
seg000:0800D784 STRB.W R4, ! ;
seg000:0800D784 ; r4=0x20001ac8里面的数据
seg000:0800D784 ; 写到
seg000:0800D784 ; R0=0x2001AF54
seg000:0800D788 CMP R1, R0;
seg000:0800D788 ; R0=0x2001af54
seg000:0800D788 ; r1=0X20001AF5C
seg000:0800D788 ; 复制16位
seg000:0800D78A UBFX.W R3, R3, #0, #0xA ; R3提取10位
seg000:0800D78E BNE loc_800D77E
seg000:0800D790 POP {R4-R6}
seg000:0800D792 BX LR
上面这个0X20001AC8和2001AE88肯定有关联的,可能通过读0X20001ACU+指针指向了0X2001AE88
我C语言不熟悉,不知道怎么写,下面这个不成功,前面从序列号移位的对,后面这个不知道用C语言怎么写,贴出来帮忙看看要怎么改
#include <stdio.h>
void main() {
unsigned int di_32, zhong_32, gao_32; //序列号
unsigned int wei8_0, wei8_1, wei8_2, wei8_3;
unsigned int wei8_4, wei8_5, wei8_6, wei8_7;
unsigned int wei8_8, wei8_9, wei8_a, wei8_b;
unsigned char mima;
unsigned int ID;
di_32 = 0x44332211;
zhong_32 = 0x77665544;
gao_32 = 0xbbaa9988;
wei8_0 = (di_32 & 0xff00) >> 8;
wei8_1 = (di_32 & 0xff) << 8;
wei8_2 = (di_32 & 0xff000000) >> 8;
wei8_3 = (di_32 & 0xff0000) << 8;
wei8_4 = (zhong_32 & 0xff00) >> 8;
wei8_5 = (zhong_32 & 0xff) << 8;
wei8_6 = (zhong_32 & 0xff000000) >> 8;
wei8_7 = (zhong_32 & 0xff0000) << 8;
wei8_8 = (gao_32 & 0xff00) >> 8;
wei8_9 = (gao_32 & 0xff) << 8;
wei8_a = (gao_32 & 0xff000000) >> 8;
wei8_b = (gao_32 & 0xff0000) << 8;
ID = wei8_0 | wei8_1 | wei8_2 | wei8_3;
ID = wei8_4 | wei8_5 | wei8_6 | wei8_7;
ID = wei8_8 | wei8_9 | wei8_a | wei8_b;
wei8_1 = wei8_1 >> 8;
wei8_2 = wei8_2 >> 16;
wei8_3 = wei8_3 >> 24;
wei8_5 = wei8_5 >> 8;
wei8_6 = wei8_6 >> 16;
wei8_7 = wei8_7 >> 24;
wei8_9 = wei8_9 >> 8;
wei8_a = wei8_a >> 16;
wei8_b = wei8_b >> 24;
di_32 = wei8_0 + wei8_1 + wei8_2 + wei8_3 + wei8_4 + wei8_5 + wei8_6 + wei8_7 + wei8_8 + wei8_9 + wei8_a + wei8_b;//每次读一个8位ID号累加
zhong_32 = di_32 & 0x3ff; //提取低10位
gao_32 = wei8_0 + wei8_b; //ID最低低8位+ID最高高8位
di_32 = gao_32 + zhong_32; //ID最高位8位+ID最低8位+累加结果提取的10位
ID = zhong_32;
ID = di_32;
for (int i = 0; i < 8; i = i + 1){
mima = ID;
di_32 = (zhong_32 + di_32) & 0x3ff;
}
printf("0x%02X0x%02X0x%02X0x%02X0x%02X0x%02X0x%02X0x%02X \n",mima,mima,mima,mima,mima,mima,mima,mima);
}
作者这个验证密码的漏洞比较大,静态分析都能看出来,要是有硬件插上JLINK一条命令就能定位,我前几年前研究过一段时间逆向,这种简单序列号保护价格可能100就有人做,他们就是把反汇编的代码放到KEIL里面重新编译然后软件仿真,估计某鱼上的就是花钱雇别人破解了卖钱而不放出来共享。
总之越用库函数和操作系统越容易被别人分析,只要做个签名文件反汇编后就直接出来函数名字了,就是不出来函数名字函数的排列也都和开发的时候一样,要是会用库开发STM32再去看别人用库写的程序反汇编后的就非常容易了,写程序的时候多费点力气别人看的时候一样也多费力气。
iffi123
发表于 2021-1-28 09:45:28
yjmwxwx 发表于 2021-1-28 09:33
要写算号器也不难,就是我C语言不怎么会用
看懂下面这两个函数就能写算号器了
越是用标准件写,越有规律,不论是标准库函数还是cube库,都如此,我现在喜欢用寄存器写(当然不是为了保密), 只是觉的代码少,直观,不象库函数的名称。参数一大串
yjmwxwx
发表于 2021-1-28 09:55:16
iffi123 发表于 2021-1-28 09:45
越是用标准件写,越有规律,不论是标准库函数还是cube库,都如此,我现在喜欢用寄存器写(当然不是为了保 ...
肯定自己写好,库函数和操作系统就是把直接操作的东西层层封装,执行效率很低,库函数那么乱看一眼都头大,根本没兴趣学怎么用。
yjmwxwx
发表于 2021-1-28 13:11:44
作者在0x20001AC8申请了4K的RAM,然后通过计算STM32唯一ID得到一个指针指向这片区域来生成密码,这片区域没有使用,不知道STM32的C语言申请一片区域后不使用里面是什么数据。
改了改差不多就是下面这样子了,现在就缺知道这4K里面是什么,再就是要有个正确的密码做比对好知道顺序。
#include <stdio.h>
void main() {
unsigned int di_32, zhong_32, gao_32; //序列号
unsigned int wei8_0, wei8_1, wei8_2, wei8_3;
unsigned int wei8_4, wei8_5, wei8_6, wei8_7;
unsigned int wei8_8, wei8_9, wei8_a, wei8_b;
unsigned char mima;
unsigned int ID;
unsigned int a, b;
di_32 = 0x38333439;
zhong_32 = 0x16513030;
gao_32 = 0x22004d00;
wei8_0 = (di_32 & 0xff00) >> 8;
wei8_1 = (di_32 & 0xff) << 8;
wei8_2 = (di_32 & 0xff000000) >> 8;
wei8_3 = (di_32 & 0xff0000) << 8;
wei8_4 = (zhong_32 & 0xff00) >> 8;
wei8_5 = (zhong_32 & 0xff) << 8;
wei8_6 = (zhong_32 & 0xff000000) >> 8;
wei8_7 = (zhong_32 & 0xff0000) << 8;
wei8_8 = (gao_32 & 0xff00) >> 8;
wei8_9 = (gao_32 & 0xff) << 8;
wei8_a = (gao_32 & 0xff000000) >> 8;
wei8_b = (gao_32 & 0xff0000) << 8;
ID = wei8_0 | wei8_1 | wei8_2 | wei8_3;
ID = wei8_4 | wei8_5 | wei8_6 | wei8_7;
ID = wei8_8 | wei8_9 | wei8_a | wei8_b;
wei8_1 = wei8_1 >> 8;
wei8_2 = wei8_2 >> 16;
wei8_3 = wei8_3 >> 24;
wei8_5 = wei8_5 >> 8;
wei8_6 = wei8_6 >> 16;
wei8_7 = wei8_7 >> 24;
wei8_9 = wei8_9 >> 8;
wei8_a = wei8_a >> 16;
wei8_b = wei8_b >> 24;
di_32 = wei8_0 + wei8_1 + wei8_2 + wei8_3 + wei8_4 + wei8_5 + wei8_6 + wei8_7 + wei8_8 + wei8_9 + wei8_a + wei8_b;//每次读一个8位ID号累加
zhong_32 = di_32 & 0x3ff; //提取低10位
gao_32 = wei8_0 + wei8_b; //ID最低低8位+ID最高高8位
di_32 = gao_32 + zhong_32; //ID最高位8位+ID最低8位+累加结果提取的10位
a = zhong_32;
b = di_32;
for (int i = 0; i < 8; i = i + 1){
mima = ID;
di_32 = (zhong_32 + di_32) & 0x3ff;
}
printf("0x%02X0x%02X0x%02X0x%02X0x%02X0x%02X0x%02X0x%02X \n",mima,mima,mima,mima,mima,mima,mima,mima);
}
执行结果肯定不对,关键就是不知道4K的RAM里面是什么
雨中狐狸
发表于 2021-1-28 13:27:46
感谢,测试过了。方法一好像不行,方法二可以
yjmwxwx
发表于 2021-1-28 13:37:14
本帖最后由 yjmwxwx 于 2021-1-28 14:02 编辑
雨中狐狸 发表于 2021-1-28 13:27
感谢,测试过了。方法一好像不行,方法二可以
方法1的LCD有显示序列号吗? 有的话要照着输入16位有效
方法1要是有显示序列号的话,我把显示的顺序搞错了,下面这个固件改过来了。
雨中狐狸
发表于 2021-1-28 14:31:42
yjmwxwx 发表于 2021-1-28 13:37
方法1的LCD有显示序列号吗? 有的话要照着输入16位有效
嗯,中间有一组0
页:
1
[2]
3
4
5
6
7
8
9
10
11