- UID
- 59317
注册时间2009-1-28
阅读权限40
最后登录1970-1-1
独步武林
TA的每日心情 | 无聊 2024-1-15 22:57 |
---|
签到天数: 3 天 [LV.2]偶尔看看I
|
pyg加油啊。。。人气有点岌岌可危了。。。
【破文标题】DeblurMyImage 1.51算法分析及算法注册机
【破文作者】zaas[PYG]
【破解工具】OllyICE,PEiD v0.94
【破解平台】WinXP
【软件类别】:国外软件/图像处理
【软件授权】:共享版
【软件介绍】:针对拍照时晃动的图形修复工具。
【破解声明】我是一只小菜鸟,偶得一点心得,愿与大家分享
--------------------------------------------------------------
【破解内容】
--------------------------------------------------------------
从清明节一直忙到端午节。几乎没跟过什么软件了。此该公司的系列软件都不是通过输入注册码什么的来注册,而是通过读取注册文件license.txt来注册的。貌似不同其实也没啥大区别,软件作者写的也很规范,加密上也没啥技术含量,而且注册文件格式比较简单,所以跟了跟。
首先查壳:Microsoft Visual C++ ver. 8.0 / Visual Studio 2005,窃喜。。。
作者指明了注册文件为license.txt,自己伪造一个文本文件,发现有弹出窗口说注册失败云云。下messgebox断下,返回一看,txt文件的内容都列出来了,可叹啊!- 0040211E |. 50 push eax ; /IniFileName
- 0040211F |. 68 00020000 push 200 ; |BufSize = 200 (512.)
- 00402124 |. 8D8C24 F02D00>lea ecx, dword ptr [esp+2DF0] ; |
- 0040212B |. 51 push ecx ; |ReturnBuffer
- 0040212C |. 68 C4F94200 push 0042F9C4 ; |Default = ""
- 00402131 |. 68 C8F94200 push 0042F9C8 ; |Key = "idcode1"
- 00402136 |. 68 D8F94200 push 0042F9D8 ; |Section = "Key"
- 0040213B |. FFD6 call esi ; \GetPrivateProfileStringW
- 0040213D |. 8D9424 E80100>lea edx, dword ptr [esp+1E8]
- 00402144 |. 52 push edx ; /IniFileName
- 00402145 |. 68 00020000 push 200 ; |BufSize = 200 (512.)
- 0040214A |. 8D8424 F02500>lea eax, dword ptr [esp+25F0] ; |
- 00402151 |. 50 push eax ; |ReturnBuffer
- 00402152 |. 68 C4F94200 push 0042F9C4 ; |Default = ""
- 00402157 |. 68 E0F94200 push 0042F9E0 ; |Key = "idcode2"
- 0040215C |. 68 D8F94200 push 0042F9D8 ; |Section = "Key"
- 00402161 |. FFD6 call esi ; \GetPrivateProfileStringW
- 00402163 |. 8D8C24 E80100>lea ecx, dword ptr [esp+1E8]
- 0040216A |. 51 push ecx ; /IniFileName
- 0040216B |. 68 00020000 push 200 ; |BufSize = 200 (512.)
- 00402170 |. 8D9424 F01500>lea edx, dword ptr [esp+15F0] ; |
- 00402177 |. 52 push edx ; |ReturnBuffer
- 00402178 |. 68 C4F94200 push 0042F9C4 ; |Default = ""
- 0040217D |. 68 F0F94200 push 0042F9F0 ; |Key = "regkey"
- 00402182 |. 68 D8F94200 push 0042F9D8 ; |Section = "Key"
- 00402187 |. FFD6 call esi ; \GetPrivateProfileStringW
- 00402189 |. 8D8424 E80100>lea eax, dword ptr [esp+1E8]
- 00402190 |. 50 push eax ; /IniFileName
- 00402191 |. 68 00020000 push 200 ; |BufSize = 200 (512.)
- 00402196 |. 8D8C24 F02900>lea ecx, dword ptr [esp+29F0] ; |
- 0040219D |. 51 push ecx ; |ReturnBuffer
- 0040219E |. 68 C4F94200 push 0042F9C4 ; |Default = ""
- 004021A3 |. 68 00FA4200 push 0042FA00 ; |Key = "username"
- 004021A8 |. 68 D8F94200 push 0042F9D8 ; |Section = "Key"
- 004021AD |. FFD6 call esi ; \GetPrivateProfileStringW
- 004021AF |. 8D9424 E80100>lea edx, dword ptr [esp+1E8]
- 004021B6 |. 52 push edx ; /IniFileName
- 004021B7 |. 68 00020000 push 200 ; |BufSize = 200 (512.)
- 004021BC |. 8D8424 F02100>lea eax, dword ptr [esp+21F0] ; |
- 004021C3 |. 50 push eax ; |ReturnBuffer
- 004021C4 |. 68 C4F94200 push 0042F9C4 ; |Default = ""
- 004021C9 |. 68 14FA4200 push 0042FA14 ; |Key = "email"
- 004021CE |. 68 D8F94200 push 0042F9D8 ; |Section = "Key"
- 004021D3 |. FFD6 call esi ; \GetPrivateProfileStringW
- 004021D5 |. 8D8C24 E80100>lea ecx, dword ptr [esp+1E8]
- 004021DC |. 51 push ecx ; /IniFileName
- 004021DD |. 68 00020000 push 200 ; |BufSize = 200 (512.)
- 004021E2 |. 8D9424 F01900>lea edx, dword ptr [esp+19F0] ; |
- 004021E9 |. 52 push edx ; |ReturnBuffer
- 004021EA |. 68 C4F94200 push 0042F9C4 ; |Default = ""
- 004021EF |. 68 20FA4200 push 0042FA20 ; |Key = "application"
- 004021F4 |. 68 D8F94200 push 0042F9D8 ; |Section = "Key"
- 004021F9 |. FFD6 call esi ; \GetPrivateProfileStringW
- 004021FB |. 8D8424 E80100>lea eax, dword ptr [esp+1E8]
- 00402202 |. 50 push eax ; /IniFileName
- 00402203 |. 68 00020000 push 200 ; |BufSize = 200 (512.)
- 00402208 |. 8D8C24 F01D00>lea ecx, dword ptr [esp+1DF0] ; |
- 0040220F |. 51 push ecx ; |ReturnBuffer
- 00402210 |. 68 C4F94200 push 0042F9C4 ; |Default = ""
- 00402215 |. 68 38FA4200 push 0042FA38 ; |Key = "usedSign"
- 0040221A |. 68 D8F94200 push 0042F9D8 ; |Section = "Key"
- 0040221F |. FFD6 call esi ; \GetPrivateProfileStringW
复制代码 下边紧接着不管你输入没输入,就把输入的内容按照格式写入了DeblurMyImage.txt,这个文件显然就是启动验证时要读取的注册文件。- 004022BA |. 50 push eax ; /FileName
- 004022BB |. 8D8C24 EC1900>lea ecx, dword ptr [esp+19EC] ; |
- 004022C2 |. 51 push ecx ; |String
- 004022C3 |. 68 20FA4200 push 0042FA20 ; |Key = "application"
- 004022C8 |. 68 D8F94200 push 0042F9D8 ; |Section = "Key"
- 004022CD |. FFD6 call esi ; \WritePrivateProfileStringW
- 004022CF |. 8D9424 E80500>lea edx, dword ptr [esp+5E8]
- 004022D6 |. 52 push edx ; /FileName
- 004022D7 |. 8D8424 EC1D00>lea eax, dword ptr [esp+1DEC] ; |
- 004022DE |. 50 push eax ; |String
- 004022DF |. 68 38FA4200 push 0042FA38 ; |Key = "usedSign"
- 004022E4 |. 68 D8F94200 push 0042F9D8 ; |Section = "Key"
- 004022E9 |. FFD6 call esi ; \WritePrivateProfileStringW
- 004022EB |. E8 20F6FFFF call 00401910 ; 关键call
- 004022F0 |. 84C0 test al, al
- 004022F2 |. 6A 00 push 0 ; /Style = MB_OK|MB_APPLMODAL
- 004022F4 |. 74 22 je short 00402318 ; |
- 004022F6 |. 68 A4244800 push 004824A4 ; |Title = "Report"
- 004022FB |. 68 A41C4800 push 00481CA4 ; |Text = "Registration was successful"
- 00402300 |. 57 push edi ; |hOwner
- 00402301 |. FF15 68C24200 call dword ptr [<&USER32.MessageBoxW>>; \MessageBoxW
- 00402307 |. 68 3A040000 push 43A ; /Result = 43A (1082.)
- 0040230C |. 57 push edi ; |hWnd
- 0040230D |. FF15 4CC24200 call dword ptr [<&USER32.EndDialog>] ; \EndDialog
- 00402313 |. E9 7E010000 jmp 00402496
- 00402318 |> 68 A4344800 push 004834A4 ; |Title = "Error"
- 0040231D |. 68 A42C4800 push 00482CA4 ; |Text = "Registration was not successful"
- 00402322 |. 57 push edi ; |hOwner
复制代码 没啥说的了,这里应该是一个struct,用c来描述下:
struct reg
{
char idcode1[0x200];
char idcode2[0x200];
char username[0x80];
char regkey[0x200];
char email[0x80];
char application[0x80];
char usedSign[0x200];
}
直接按照格式伪造txt文件。
- [key]
- idcode1=123
- idcode2=123
- regkey=123
- username=zaas
- email=123
- application=123
- usedSign=123
复制代码 重新读取license.txt。关键call也是明摆着的,直接跟进去找。- 00401910 /$ 51 push ecx
- 00401911 |. 53 push ebx
- 00401912 |. 6A 01 push 1
- 00401914 |. E8 27F8FFFF call 00401140 ; 算法1
- 00401919 |. 6A 00 push 0
- 0040191B |. 8AD8 mov bl, al ; 标志位
- 0040191D |. E8 1EF8FFFF call 00401140 ; 为了保险再来一遍?
- 00401922 |. 83C4 08 add esp, 8
- 00401925 |. 884424 07 mov byte ptr [esp+7], al ; 标志位
- 00401929 |. E8 B2FEFFFF call 004017E0 ; 算法2
- 0040192E |. 84DB test bl, bl
- 00401930 |. 5B pop ebx
- 00401931 |. 75 07 jnz short 0040193A
- 00401933 |. 807C24 03 00 cmp byte ptr [esp+3], 0
- 00401938 |. 74 0B je short 00401945
- 0040193A |> 84C0 test al, al
- 0040193C |. 75 07 jnz short 00401945
- 0040193E |. B8 01000000 mov eax, 1 ; 需跳到这里
- 00401943 |. 59 pop ecx
- 00401944 |. C3 retn
- 00401945 |> 33C0 xor eax, eax ; 这里就完了
- 00401947 |. 59 pop ecx
- 00401948 \. C3 retn
复制代码 没啥,继续跟进吧。。。
此处有一个对软件名称的判断,如果软件名称不对,直接跳死。- 00401397 |. BE A0F94200 mov esi, 0042F9A0 ; ASCII "DeblurMyImage"
- 0040139C |. B9 0E000000 mov ecx, 0E
- 004013A1 |. 33D2 xor edx, edx
- 004013A3 |. F3:A6 repe cmps byte ptr es:[edi], byte ptr>; 检查application是不是DeblurMyImage
- 004013A5 |. 74 19 je short 004013C0 ; 不是跳死
- 004013A7 |. 5F pop edi
- 004013A8 |. 32C0 xor al, al
- 004013AA |. 5E pop esi
- 004013AB |. 8B8C24 004900>mov ecx, dword ptr [esp+4900]
- 004013B2 |. 33CC xor ecx, esp
- 004013B4 |. E8 C17E0100 call 0041927A
- 004013B9 |. 81C4 04490000 add esp, 4904
- 004013BF |. C3 retn
- 004013C0 |> 53 push ebx
- 004013C1 |. 68 00020000 push 200
- 004013C6 |. 8D8424 100100>lea eax, dword ptr [esp+110]
- 004013CD |. 6A 00 push 0
- 004013CF |. 50 push eax
- 004013D0 |. E8 ABC80100 call 0041DC80 ; new出空间
- 004013D5 |. 68 00020000 push 200
- 004013DA |. 8D8C24 1C1300>lea ecx, dword ptr [esp+131C]
- 004013E1 |. 6A 00 push 0
- 004013E3 |. 51 push ecx
- 004013E4 |. E8 97C80100 call 0041DC80 ; new出空间
- 004013E9 |. 8D9424 240100>lea edx, dword ptr [esp+124]
- 004013F0 |. 52 push edx
- 004013F1 |. E8 FA4F0100 call 004163F0 ; 固定字符串"DS$58j((4hKdh40_u55tJ48ak49j"转为ascii码字符串 ,记为StrA
- 004013F6 |. 8D8424 281300>lea eax, dword ptr [esp+1328]
复制代码 继续向下走,进入算法部分:- 0040143C |. 8D8424 181900>lea eax, dword ptr [esp+1918] ; 取idcode1
- 00401443 |. 83C4 0C add esp, 0C
- 00401446 |. 50 push eax
- 00401447 |. 8D8C24 100100>lea ecx, dword ptr [esp+110]
- 0040144E |. E8 4D520100 call 004166A0
- 00401453 |. 8D8C24 100B00>lea ecx, dword ptr [esp+B10] ; 取idcode2
- 0040145A |. 51 push ecx
- 0040145B |. 8D8C24 140100>lea ecx, dword ptr [esp+114]
- 00401462 |. E8 39520100 call 004166A0
- ......
- 004014B7 |. 83C4 18 add esp, 18
- 004014BA |. 8D8C24 0C2300>lea ecx, dword ptr [esp+230C] ; 从以上算出的regkey假码
- 004014C1 |. 8D8424 0C0100>lea eax, dword ptr [esp+10C] ; regkey的真码
- 004014C8 |> 8A10 /mov dl, byte ptr [eax] ; 比较
- 004014CA |. 3A11 |cmp dl, byte ptr [ecx]
- 004014CC |. 75 1A |jnz short 004014E8
- 004014CE |. 84D2 |test dl, dl
- 004014D0 |. 74 12 |je short 004014E4
- 004014D2 |. 8A50 01 |mov dl, byte ptr [eax+1]
- 004014D5 |. 3A51 01 |cmp dl, byte ptr [ecx+1]
- 004014D8 |. 75 0E |jnz short 004014E8
- 004014DA |. 83C0 02 |add eax, 2
- 004014DD |. 83C1 02 |add ecx, 2
- 004014E0 |. 84D2 |test dl, dl
- 004014E2 |.^ 75 E4 \jnz short 004014C8
- 004014E4 |> 33C0 xor eax, eax ; 成功
- 004014E6 |. EB 05 jmp short 004014ED
- 004014E8 |> 1BC0 sbb eax, eax ; 失败
- 004014EA |. 83D8 FF sbb eax, -1
- 004014ED |> 85C0 test eax, eax
复制代码 根据固定字符串StrA和注册文件的各项内容算出一个regkey,和注册文件中的regkey对比,如果不同就完蛋了。
如果不是研究算法,直接在这里把真码贴注册文件里就OK了。继续:
下边算法比较啰嗦,固定字符串拆了合,合了拆,没啥变化,现在电脑运算速度快,作者也不在乎了。
输入的各项字符串变化方式如下:- 00416010 /$ 33C9 xor ecx, ecx
- 00416012 |. 85FF test edi, edi
- 00416014 |. 7E 31 jle short 00416047
- 00416016 |> 8A5431 01 /mov dl, byte ptr [ecx+esi+1] ; 取第二个字符
- 0041601A |. 80FA 3A |cmp dl, 3A ; 是不是数字以下ascii字符
- 0041601D |. 73 05 |jnb short 00416024 ; 不是+0xA9,是+0xD0
- 0041601F |. 80C2 D0 |add dl, 0D0
- 00416022 |. EB 03 |jmp short 00416027
- 00416024 |> 80C2 A9 |add dl, 0A9
- 00416027 |> 8A0431 |mov al, byte ptr [ecx+esi] ; 取第一个字符
- 0041602A |. 3C 3A |cmp al, 3A ; 如法炮制
- 0041602C |. 73 04 |jnb short 00416032
- 0041602E |. 04 D0 |add al, 0D0
- 00416030 |. EB 02 |jmp short 00416034
- 00416032 |> 04 A9 |add al, 0A9
- 00416034 |> C0E0 04 |shl al, 4 ; 第一个字符左移4
- 00416037 |. 02C2 |add al, dl ; +第二个字符,两个字符通过以上合并成一个值
- 00416039 |. 8BD1 |mov edx, ecx
- 0041603B |. D1EA |shr edx, 1
- 0041603D |. 83C1 02 |add ecx, 2
- 00416040 |. 3BCF |cmp ecx, edi
- 00416042 |. 88041A |mov byte ptr [edx+ebx], al ; 保存
- 00416045 |.^ 7C CF \jl short 00416016
- 00416047 \> C3 retn
复制代码 字符串变完之后要和固定字符串运算了。- 00416770 |> 33D2 /xor edx, edx
- 00416772 |. |8BC1 |mov eax, ecx
- 00416774 |. |F7F6 |div esi
- 00416776 |. |0FB6840C 1402>|movzx eax, byte ptr [esp+ecx+214] ; 第一次:固定字符串DS$58j((4hKdh40_u55tJ48ak49j取字符
- 0041677E |. |0FB65414 14 |movzx edx, byte ptr [esp+edx+14] ; 和变换后的idcode1做加法
- 00416783 |. |03D0 |add edx, eax
- 00416785 |. |81E2 FF000080 |and edx, 800000FF ; 取char长度
- 0041678B |. |79 08 |jns short 00416795
- 0041678D |. |4A |dec edx
- 0041678E |. |81CA 00FFFFFF |or edx, FFFFFF00
- 00416794 |. |42 |inc edx
- 00416795 |> |88940C 140200>|mov byte ptr [esp+ecx+214], dl ; 写回固定字符串的地址
- 0041679C |. |83C1 01 |add ecx, 1 ; 计数器
- 0041679F |. |3BCF |cmp ecx, edi
- 004167A1 |.^\72 CD \jb short 00416770
- 004167A3 |> 8BCB mov ecx, ebx
- 004167A5 |. 8DB424 140200>lea esi, dword ptr [esp+214]
- 004167AC |. E8 0FF8FFFF call 00415FC0 ; 转回ascii字符串
复制代码 本来以为就这样完了,接下去发现了新问题:idcode2不是风吹来的,是根据一个固定字符串和"computername","username"算出来的。计算方法和上边一致。悲剧的是,idcode2全部是固定字符串的来的,运算方法再复杂,最终会明码出现idcode2。真是多此一举啊。。。
懒得跟了,直接把idcode2抄写下来就可以写注册机了。
算法不复杂,也不再总结了。
以后不再写算法类文章了,好好学我的C吧。以此为总结。
注册机是按照denoisemyimage写的,算法一样,不同的是字符串。ok。- #include "key.h"
- void ClearStr (char * str,int len)
- {
- for (int i=0;i<len;i++)
- {
- *(str+i)=0;
- }
- }
- int StrToAscStr(char *pd,char *ps)
- {
- char *temp;
- temp=(char *)malloc(sizeof(char)*4);
-
- ClearStr(pd,MAX);
- for (unsigned int i=0;i<strlen(ps);i++)
- {
- ClearStr(temp,4);
- sprintf(temp,"%02x",(unsigned char)*(ps+i));
- strcat(pd,temp);
- }
- free(temp);
- return i;
- }
- int ProcessStr(char * dist,char * source)
- {
- unsigned int len;
- char *temp1,*temp2;
- temp1=(char *)malloc(sizeof(char)*MAX);
- temp2=(char *)malloc(sizeof(char)*MAX);
- ClearStr(temp1,MAX);
- ClearStr(temp2,MAX);
- char attach[5]={0xc,0xb,7,3,0};
- AscStrToStr(temp1,source);
- len=strlen(source)+4;
- strcat(temp2,attach);
- strcat(temp2,temp1);
- unsigned int k=0;
- for (unsigned int i=0;i<strlen(dist);i++)
- {
- if (len==k) k=0;
- *(dist+i)+=*(temp2+k);
- k++;
- }
- free(temp1);
- free(temp2);
- return 1;
- }
- void GetRandStr(char *str,char *index,int len)
- {
- for (int i=0;i<len;i++)
- {
- *(str+i)=*(index+rand()%strlen(index));
- }
- }
- void AscStrToStr(char *pd,char *ps)
- {
- char a,b;
- unsigned int len;
- if (strlen(ps)%2) len=strlen(ps)/2+1;
- else len=strlen(ps)/2;
- ClearStr(pd,MAX);
- for (unsigned int i=0;i<len;i++)
- {
- a=*(ps+2*i+1);
- if (a<0x3a) a +=0xd0;
- else a+=0xa9;
- b=*(ps+2*i);
- if (b<0x3a) b+=0xd0;
- else b+=0xa9;
- *(pd+i)=(b<<4)+a;
- }
- }
- void run(char *username)
- {
- srand((int)time(0));
- char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
- char path[]="C:\\license.txt";
- char *code1,*regkey,*usedSign,*email;
- char Soft[]="DenoiseMyImageGPU20";
- char code2[]="88878174847b79cbbfc0632d0be243c5d188b7d0bda8e59d8da9ada0";
- int len;
-
- regkey=(char *)malloc(sizeof(char)*MAX);
- code1=(char *)malloc(sizeof(char)*MAX);
- usedSign=(char *)malloc(sizeof(char)*MAX);
- email=(char *)malloc(sizeof(char)*MAX);
- //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
- //有可能和为0,此时字符串长度有问题
- //所以要加一个while循环
- //此时把malloc都放在循环体外部
- //ref 不放在循环体内的话,每次修改都在原有基础上改,while循环就出错挑不出去了
- //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- do
- {
- char ref[]="DS$58j((4hKdh40_u55tJ48ak49j";
- char temp[10];
- ClearStr(temp,10);
- ClearStr(regkey,MAX);
- ClearStr(code1,MAX);
- ClearStr(usedSign,MAX);
- ClearStr(email,MAX);
-
- GetRandStr(code1,index,56);
- GetRandStr(usedSign,index,56);
- GetRandStr(temp,index,8);
-
- strcat(email,username);
- strcat(email,temp);
-
- ProcessStr(ref,code1);
- ProcessStr(ref,code2);
- ProcessStr(ref,username);
- ProcessStr(ref,email);
- ProcessStr(ref,Soft);
- ProcessStr(ref,usedSign);
-
- len=StrToAscStr(regkey,ref);
-
- } while (len!=28);
-
- FILE *fp;
- fp=fopen(path,"w");
- fprintf(fp,"[Key]\n\n");
- fprintf(fp,"application=DenoiseMyImageGPU20\n");
- fprintf(fp,"username=%s\n",username);
- fprintf(fp,"email=%s\n",email);
- fprintf(fp,"idcode1=%s\n",code1);
- fprintf(fp,"idcode2=%s\n",code2);
- fprintf(fp,"usedSign=%s\n",usedSign);
- fprintf(fp,"regkey=%s\n",regkey);
-
- fclose(fp);
-
- free(email);
- free(regkey);
- free(code1);
- free(usedSign);
- }
复制代码 【版权声明】破文是学习的手记,兴趣是成功的源泉;本破文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢! |
评分
-
查看全部评分
|