【文章标题】: 两个 rsa 加密的程序
【文章作者】: rdsnow[BCG][PYG][D.4s]
【作者邮箱】: [email]rdsnow@163.com[/email]
【作者主页】: http://rdsnow.ys168.com
【作者QQ号】: 83757177
【下载地址】: Allok Video Splitter:http://www.alloksoft.com/allok_vsplitter.exe
All Video Splitter:http://www.zealotsoft.net/download/allsplitter.exe
【保护方式】: RSA
【使用工具】: ODbyDYK v1.10[05.09] rsa_toolII V1.10 ppsiqs
【软件介绍】: a tool to split, cut or trim a video file.
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
【文章简介】
感觉很多视频处理程序采用了RSA对程序保护,我下载了几个视频剪接工具,竟然有不少使用了RSA1024,最后一个个放弃,最后找了两个容易的,高手就不要看了。rsa256的可以作出注册机,rsa1024就干脆暴算了。
--------------------------------------------------------------------------------
【破解过程】
Allok Video Splitter 1.6.4
程序友好提示注册码是:XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX,跟进才发现上当了,注册码有 8 段,试探性的输入:
username = "rdsnow[BCG][PYG][D.4s]";
serial = "9876abcd-4321abcd-1234abcd-5678abcd-9876cdef-4321cdef-1234cdef-5678cdef";
然后 Ultra String Reference 搜索错误信息,很容易找到关键代码:
要注意该程序试用的大数运算库中,大数表示是低位在前,高位在后,跟
0040F1D9 . 50 PUSH EAX
0040F1DA . 51 PUSH ECX
0040F1DB . E8 A0E4FFFF CALL Allok_Vi.0040D680 ; 关键调用
0040F1E0 . 83C4 08 ADD ESP,8
0040F1E3 . 85C0 TEST EAX,EAX
0040F1E5 . 75 2B JNZ SHORT Allok_Vi.0040F212 ; 关键跳跃
0040F1E7 . 6A 40 PUSH 40
0040F1E9 . 68 44284200 PUSH Allok_Vi.00422844 ; ASCII "Sorry"
0040F1EE . 68 20284200 PUSH Allok_Vi.00422820 ; ASCII "Invalid user name or register code"
0040F1F3 . 8BCD MOV ECX,EBP
0040F1F5 . E8 14900000 CALL <JMP.&MFC42.#4224_CWnd::MessageBoxA>
……………………
0040F236 . 50 PUSH EAX ; /<%s>
0040F237 . 8D8424 DC0000>LEA EAX,DWORD PTR SS:[ESP+DC] ; |
0040F23E . 68 F8274200 PUSH Allok_Vi.004227F8 ; |format = "Register successful! License to:%s. "
0040F243 . 50 PUSH EAX ; |s
0040F244 . FF15 38B64100 CALL DWORD PTR DS:[<&MSVCRT.sprintf>] ; \sprintf
跟进 40D680:
0040D680 /$ 6A FF PUSH -1
0040D682 |. 68 D9954100 PUSH Allok_Vi.004195D9 ; SE 处理程序安装
0040D687 |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0]
0040D68D |. 50 PUSH EAX
0040D68E |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP
0040D695 |. 81EC 94000000 SUB ESP,94
0040D69B |. 8B8424 A40000>MOV EAX,DWORD PTR SS:[ESP+A4]
0040D6A2 |. 53 PUSH EBX
0040D6A3 |. 56 PUSH ESI
0040D6A4 |. 50 PUSH EAX
0040D6A5 |. 8D4C24 10 LEA ECX,DWORD PTR SS:[ESP+10]
0040D6A9 |. C74424 60 C38>MOV DWORD PTR SS:[ESP+60],E6A982C3 ; n = 0x5F935AC64498D4D5A20B6EAFCC6515DF03EBDAB4FE566A7D4E09CA73E6A982C3
0040D6B1 |. C74424 64 73C>MOV DWORD PTR SS:[ESP+64],4E09CA73
0040D6B9 |. C74424 68 7D6>MOV DWORD PTR SS:[ESP+68],FE566A7D
0040D6C1 |. C74424 6C B4D>MOV DWORD PTR SS:[ESP+6C],3EBDAB4
0040D6C9 |. C74424 70 DF1>MOV DWORD PTR SS:[ESP+70],CC6515DF ; 注意,按照高位在后,低位在前的原则得到 n
0040D6D1 |. C74424 74 AF6>MOV DWORD PTR SS:[ESP+74],A20B6EAF
0040D6D9 |. C74424 78 D5D>MOV DWORD PTR SS:[ESP+78],4498D4D5
0040D6E1 |. C74424 7C C65>MOV DWORD PTR SS:[ESP+7C],5F935AC6
0040D6E9 |. E8 88A90000 CALL <JMP.&MFC42.#537_CString::CString> ; CString username = "rdsnow[BCG][PYG][D.4s]"
0040D6EE |. 8B8C24 B00000>MOV ECX,DWORD PTR SS:[ESP+B0]
0040D6F5 |. C78424 A40000>MOV DWORD PTR SS:[ESP+A4],0
0040D700 |. 51 PUSH ECX
0040D701 |. 8D4C24 0C LEA ECX,DWORD PTR SS:[ESP+C]
0040D705 |. E8 6CA90000 CALL <JMP.&MFC42.#537_CString::CString> ; CString serial = "9876abcd-4321abcd-1234abcd-5678abcd-9876cdef-4321cdef-1234cdef-5678cdef"
0040D70A |. 8B5424 0C MOV EDX,DWORD PTR SS:[ESP+C]
0040D70E |. 8B35 28B64100 MOV ESI,DWORD PTR DS:[<&MSVCRT._mbscmp>] ; msvcrt._mbscmp
0040D714 |. 68 04354200 PUSH Allok_Vi.00423504 ; /s2 = ""
0040D719 |. 52 PUSH EDX ; |s1
0040D71A |. C68424 AC0000>MOV BYTE PTR SS:[ESP+AC],1 ; |
0040D722 |. FFD6 CALL ESI ; \_mbscmp
0040D724 |. 83C4 08 ADD ESP,8
0040D727 |. 85C0 TEST EAX,EAX
0040D729 |. 0F84 0F020000 JE Allok_Vi.0040D93E ; if(username=="") return flase
0040D72F |. 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8]
0040D733 |. 68 04354200 PUSH Allok_Vi.00423504 ; /s2 = ""
0040D738 |. 50 PUSH EAX ; |s1
0040D739 |. FFD6 CALL ESI ; \_mbscmp
0040D73B |. 83C4 08 ADD ESP,8
0040D73E |. 85C0 TEST EAX,EAX
0040D740 |. 0F84 F8010000 JE Allok_Vi.0040D93E ; if(serial=="") return flase
0040D746 |. 57 PUSH EDI
以上是注册的第一步,检查是否受到用户名和注册码的输入,如果没有输入就返回 false,同时,我们也已经找到了 RSA 算法中的公钥 e 和模 n,可以进入下一步参与大数运算了。
0040D747 |. 6A 00 PUSH 0
0040D749 |. 8D4C24 44 LEA ECX,DWORD PTR SS:[ESP+44]
0040D74D |. E8 3E830000 CALL Allok_Vi.00415A90 ; bigint n 初始化
0040D752 |. 6A 00 PUSH 0
0040D754 |. 8D4C24 4C LEA ECX,DWORD PTR SS:[ESP+4C]
0040D758 |. C68424 AC0000>MOV BYTE PTR SS:[ESP+AC],2
0040D760 |. E8 2B830000 CALL Allok_Vi.00415A90 ; bigint m 初始化
0040D765 |. B3 03 MOV BL,3
0040D767 |. 68 01000100 PUSH 10001 ; 注意这个数值
0040D76C |. 8D4C24 5C LEA ECX,DWORD PTR SS:[ESP+5C]
0040D770 |. 889C24 AC0000>MOV BYTE PTR SS:[ESP+AC],BL
0040D777 |. E8 14830000 CALL Allok_Vi.00415A90 ; bigint e = 0x10001
0040D77C |. 8D4C24 58 LEA ECX,DWORD PTR SS:[ESP+58]
0040D780 |. C68424 A80000>MOV BYTE PTR SS:[ESP+A8],4
0040D788 |. 51 PUSH ECX
0040D789 |. 8D4C24 4C LEA ECX,DWORD PTR SS:[ESP+4C]
0040D78D |. E8 5E830000 CALL Allok_Vi.00415AF0
0040D792 |. 8D4C24 58 LEA ECX,DWORD PTR SS:[ESP+58]
0040D796 |. 889C24 A80000>MOV BYTE PTR SS:[ESP+A8],BL
0040D79D |. E8 9E830000 CALL Allok_Vi.00415B40
0040D7A2 |. 8D5424 60 LEA EDX,DWORD PTR SS:[ESP+60]
0040D7A6 |. 6A 08 PUSH 8
0040D7A8 |. 52 PUSH EDX
0040D7A9 |. 8D4C24 48 LEA ECX,DWORD PTR SS:[ESP+48]
0040D7AD |. E8 AE810000 CALL Allok_Vi.00415960
0040D7B2 |. B9 08000000 MOV ECX,8
0040D7B7 |. 33C0 XOR EAX,EAX
0040D7B9 |. 8D7C24 18 LEA EDI,DWORD PTR SS:[ESP+18]
0040D7BD |. 8D5424 2C LEA EDX,DWORD PTR SS:[ESP+2C]
0040D7C1 |. F3:AB REP STOS DWORD PTR ES:[EDI]
0040D7C3 |. 8D4424 34 LEA EAX,DWORD PTR SS:[ESP+34]
0040D7C7 |. 8D4C24 30 LEA ECX,DWORD PTR SS:[ESP+30]
0040D7CB |. 50 PUSH EAX
0040D7CC |. 51 PUSH ECX
0040D7CD |. 8D4424 30 LEA EAX,DWORD PTR SS:[ESP+30]
0040D7D1 |. 52 PUSH EDX
0040D7D2 |. 8D4C24 30 LEA ECX,DWORD PTR SS:[ESP+30]
0040D7D6 |. 50 PUSH EAX
0040D7D7 |. 8D5424 30 LEA EDX,DWORD PTR SS:[ESP+30]
0040D7DB |. 51 PUSH ECX
0040D7DC |. 8D4424 30 LEA EAX,DWORD PTR SS:[ESP+30]
0040D7E0 |. 52 PUSH EDX
0040D7E1 |. 8B5424 24 MOV EDX,DWORD PTR SS:[ESP+24]
0040D7E5 |. 8D4C24 30 LEA ECX,DWORD PTR SS:[ESP+30]
0040D7E9 |. 50 PUSH EAX
0040D7EA |. 51 PUSH ECX
0040D7EB |. 68 68274200 PUSH Allok_Vi.00422768 ; |format = "%08lX-%08lX-%08lX-%08lX-%08lX-%08lX-%08lX-%08lX
"
0040D7F0 |. 52 PUSH EDX ; |s
0040D7F1 |. FF15 34B64100 CALL DWORD PTR DS:[<&MSVCRT.sscanf>] ; \sscanf
0040D7F7 |. 8B4424 50 MOV EAX,DWORD PTR SS:[ESP+50] ; s4
0040D7FB |. 8B4C24 4C MOV ECX,DWORD PTR SS:[ESP+4C] ; s3
0040D7FF |. 8B7C24 48 MOV EDI,DWORD PTR SS:[ESP+48] ; s2
0040D803 |. 8B5424 44 MOV EDX,DWORD PTR SS:[ESP+44] ; s1
0040D807 |. 03C1 ADD EAX,ECX ; result1 = s4 + s3
0040D809 |. 8B4C24 5C MOV ECX,DWORD PTR SS:[ESP+5C] ; s7
0040D80D |. 03C7 ADD EAX,EDI ; result1 += s2
0040D80F |. 8B7C24 58 MOV EDI,DWORD PTR SS:[ESP+58] ; s6
0040D813 |. 03C2 ADD EAX,EDX ; result1 += s1
0040D815 |. 8B5424 40 MOV EDX,DWORD PTR SS:[ESP+40] ; s0
0040D819 |. 33C8 XOR ECX,EAX ; result1 ^= s7
0040D81B |. 8B4424 54 MOV EAX,DWORD PTR SS:[ESP+54] ; s5
0040D81F |. 83C4 28 ADD ESP,28
0040D822 |. 03C2 ADD EAX,EDX ; result2 = s0 + s5
0040D824 |. 894C24 34 MOV DWORD PTR SS:[ESP+34],ECX ; save result1=(s1+s2+s3+s4)^s7
0040D828 |. 33F8 XOR EDI,EAX ; result2 ^= s6
0040D82A |. 6A 00 PUSH 0
0040D82C |. 8D4C24 3C LEA ECX,DWORD PTR SS:[ESP+3C]
0040D830 |. 897C24 34 MOV DWORD PTR SS:[ESP+34],EDI ; save result2=(s0+s5)^s6
0040D834 |. E8 57820000 CALL Allok_Vi.00415A90 ; bigint m = result
以上到了注册的第二步,如果注册码是 s0-s1-s2-s3-s4-s5-s6-s7,首先把 s6 和 s7 原先处理一下,处理的方法是:
s6 = ( s0 + s5 ) ^ s6
s7 = ( s1 + s2 + s3 + s4 ) ^ s7
然后按照低位前,高位后的原则:m = s7s6s5s4s3s2s1s0
比如我输入的serial是:9876abcd-4321abcd-1234abcd-5678abcd-9876cdef-4321cdef-1234cdef-5678cdef
s6 变换为:0xC9ACB453
s7 变化为:0x123D1CB9
最后,m = 0x123D1CB9C9ACB4534321CDEF9876CDEF5678ABCD1234ABCD4321ABCD9876ABCD
0040D839 |. 8D4C24 18 LEA ECX,DWORD PTR SS:[ESP+18]
0040D83D |. 6A 08 PUSH 8
0040D83F |. 51 PUSH ECX
0040D840 |. 8D4C24 40 LEA ECX,DWORD PTR SS:[ESP+40]
0040D844 |. C68424 B00000>MOV BYTE PTR SS:[ESP+B0],5
0040D84C |. E8 0F810000 CALL Allok_Vi.00415960 ; rsa_de( ),计算 c = m^e mod n
0040D851 |. 8D5424 38 LEA EDX,DWORD PTR SS:[ESP+38]
0040D855 |. 8D4424 50 LEA EAX,DWORD PTR SS:[ESP+50]
0040D859 |. 52 PUSH EDX
0040D85A |. 50 PUSH EAX
0040D85B |. 8D4C24 48 LEA ECX,DWORD PTR SS:[ESP+48]
0040D85F |. E8 2C060000 CALL Allok_Vi.0040DE90 ; 结果以大数输出 c
0040D864 |. B9 08000000 MOV ECX,8
0040D869 |. 33C0 XOR EAX,EAX
0040D86B |. 8D7C24 18 LEA EDI,DWORD PTR SS:[ESP+18]
0040D86F |. 6A 08 PUSH 8
0040D871 |. F3:AB REP STOS DWORD PTR ES:[EDI]
0040D873 |. 8D4C24 1C LEA ECX,DWORD PTR SS:[ESP+1C]
0040D877 |. C68424 AC0000>MOV BYTE PTR SS:[ESP+AC],6
0040D87F |. 51 PUSH ECX
0040D880 |. 8D4C24 58 LEA ECX,DWORD PTR SS:[ESP+58]
0040D884 |. E8 17810000 CALL Allok_Vi.004159A0 ; 大数结果转为十六进制字节串 c
0040D889 |. B9 08000000 MOV ECX,8
0040D88E |. 33C0 XOR EAX,EAX
0040D890 |. 8DBC24 800000>LEA EDI,DWORD PTR SS:[ESP+80]
0040D897 |. F3:AB REP STOS DWORD PTR ES:[EDI]
0040D899 |. 5F POP EDI ; 以下交换每一个dword的高位和低位
0040D89A |> 8A5404 17 /MOV DL,BYTE PTR SS:[ESP+EAX+17]
0040D89E |. 8A4C04 16 |MOV CL,BYTE PTR SS:[ESP+EAX+16]
0040D8A2 |. 885404 7C |MOV BYTE PTR SS:[ESP+EAX+7C],DL
0040D8A6 |. 8B5404 14 |MOV EDX,DWORD PTR SS:[ESP+EAX+14]
0040D8AA |. 884C04 7D |MOV BYTE PTR SS:[ESP+EAX+7D],CL
0040D8AE |. 8A4C04 14 |MOV CL,BYTE PTR SS:[ESP+EAX+14]
0040D8B2 |. C1EA 08 |SHR EDX,8
0040D8B5 |. 885404 7E |MOV BYTE PTR SS:[ESP+EAX+7E],DL
0040D8B9 |. 884C04 7F |MOV BYTE PTR SS:[ESP+EAX+7F],CL
0040D8BD |. 83C0 04 |ADD EAX,4
0040D8C0 |. 83F8 20 |CMP EAX,20
0040D8C3 |.^ 7C D5 \JL SHORT Allok_Vi.0040D89A
这里到了注册的第三步:对以上信息RSA运算,并将结果分成 8 个dword,将每一个dword 的高位和低位交换
0040D8C5 |. 8D5424 7C LEA EDX,DWORD PTR SS:[ESP+7C]
0040D8C9 |. 8D4C24 10 LEA ECX,DWORD PTR SS:[ESP+10]
0040D8CD |. 52 PUSH EDX
0040D8CE |. E8 A3A70000 CALL <JMP.&MFC42.#537_CString::CString>
0040D8D3 |. 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10]
0040D8D7 |. 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C]
0040D8DB |. 50 PUSH EAX
0040D8DC |. 51 PUSH ECX
0040D8DD |. FFD6 CALL ESI ; rsa 结果跟用户名比较
0040D8DF |. 83C4 08 ADD ESP,8
0040D8E2 |. 8D4C24 10 LEA ECX,DWORD PTR SS:[ESP+10]
0040D8E6 |. 85C0 TEST EAX,EAX
0040D8E8 |. C68424 A40000>MOV BYTE PTR SS:[ESP+A4],6
0040D8F0 |. 0F84 86000000 JE Allok_Vi.0040D97C ; 关键跳跃
0040D8F6 |. E8 F7A30000 CALL <JMP.&MFC42.#800_CString::~CString>
0040D8FB |. 8D4C24 4C LEA ECX,DWORD PTR SS:[ESP+4C]
……………………
0040D964 |. 33C0 XOR EAX,EAX ; return false
0040D966 |. 5B POP EBX
0040D967 |. 8B8C24 940000>MOV ECX,DWORD PTR SS:[ESP+94]
0040D96E |. 64:890D 00000>MOV DWORD PTR FS:[0],ECX
0040D975 |. 81C4 A0000000 ADD ESP,0A0
0040D97B |. C3 RETN
0040D97C |> \E8 71A30000 CALL <JMP.&MFC42.#800_CString::~CString>
0040D981 |. 8D4C24 4C LEA ECX,DWORD PTR SS:[ESP+4C]
……………………
0040D9E9 |. 8B8C24 9C0000>MOV ECX,DWORD PTR SS:[ESP+9C]
0040D9F0 |. 5E POP ESI
0040D9F1 |. B8 01000000 MOV EAX,1 ; return true
0040D9F6 |. 5B POP EBX
0040D9F7 |. 64:890D 00000>MOV DWORD PTR FS:[0],ECX
0040D9FE |. 81C4 A0000000 ADD ESP,0A0
0040DA04 \. C3 RETN
--------------------------------------------------------------------------------
既然已经找到了模数 n ,我们得化一些时间去分解这个模数,将数值转为十进制,复制到 ppsiqs 窗口,然后等待......
还好256位的数值分解,ppsiqs完全可以胜任,Sempron 2200+ 256M DDR 运行,几十分钟后,PPsigs 的 logo 文件中给出答案:
43230073636397487656983558936559823181690578386630754424326657423034966180547 = P39 * P39
P39 = 152459900927658332219918333765741632151
P39 = 283550450796304794710461168046173026997
cputime 0:33:53:29
然后rsa_tool计算出密钥 d,由此可得:
n:5F935AC64498D4D5A20B6EAFCC6515DF03EBDAB4FE566A7D4E09CA73E6A982C3
p:72B2B5774A8A54DCC5BC6B499852DA97
q:D551D494A7EE88B04694CF5CD17F7AB5
e:10001
d:3B60C4E8A0FD825D274B8AFCD533881E35FB43F58255A6962D7E8878D5B2A9A1
程序拿 RSA_de 的结果和用户名比较,判断是否授权
拿 username 得到 serial 的运算过程是:现将 username 分成若干 dword,并交换 dword 的高位和低位,我的用户名是:rdsnow[BCG][PYG][D.4s]
换位后得到:c = s]/0/0[D.sPYG]CG][ow[Brdsn,注意中间的两个'/0',如果 strlen(username) 是四的整数倍,则不会出现,按照顺序转为 HEX 文本,然后 RSA_en,最后用
s6 = ( s0 + s5 ) ^ s6
s7 = ( s1 + s2 + s3 + s4 ) ^ s7
恢复 s6 和 s7。
另外程序中没有对 m 和 c 是否大于 n 的判断,所以建议 strlen(username) 小于 32 ,以确保 m 不会大于 n。
注册信息保存在 data.ini 中,删了这个文件,程序就会变成未注册版。
--------------------------------------------------------------------------------
【注册机源码】
用 miracl 运算库写个 keygen ,要注意 mriacl 的 big_to_bytes 输出的字节串是高位在前的,跟程序中不同,要注意改过来。
extern "C"
{
#include "miracl.h"
#include "mirdef.h"
}
#pragma comment( lib, "ms32.lib" )
void CKeygenDlg::OnOK()
{
// TODO: Add extra validation here
byte username[32]={0},i;
char temp[4];
TCHAR buff[68]={0};
UINT serial[8];
Beep(1000,10);
UpdateData(true);
i=m_Edit1.GetLength ();
memcpy (username,m_Edit1,i+1);
//将用户名每四个字符倒序,并转成十六进制字符串
for(i=32;i>0;i=i-4){
sprintf(temp,"%02X",username[i-4]);strcat((char *)buff,temp);
sprintf(temp,"%02X",username[i-3]);strcat((char *)buff,temp);
sprintf(temp,"%02X",username[i-2]);strcat((char *)buff,temp);
sprintf(temp,"%02X",username[i-1]);strcat((char *)buff,temp);
}
//MIRACL大数运算库运算
miracl *mip=mirsys(100,0);
mip->IOBASE=16; //16进制模式
//定义并初始化变量
big m=mirvar(0); //m 放明文:注册码serial
big c=mirvar(0); //c 放密文:用户名username
big n=mirvar(0); //n 模数
big d=mirvar(0); //d 私钥
cinstr(c,buff); //初始化密文c
memset(buff,0,68);
cinstr(n,"5F935AC64498D4D5A20B6EAFCC6515DF03EBDAB4FE566A7D4E09CA73E6A982C3"); //初始化模数n
cinstr(d,"3B60C4E8A0FD825D274B8AFCD533881E35FB43F58255A6962D7E8878D5B2A9A1"); //初始化私钥e
powmod(c,d,n,m); //计算m=c^d mod n
big_to_bytes(0,m,buff,FALSE); //将c转换成数组写入buff
mirkill(m);
mirkill(c);
mirkill(n);
mirkill(d);
mirexit();
for(i=0;i<8;i++){
serial[7-i]=(byte)buff[(i<<2)];
serial[7-i]=(serial[7-i]<<8)+(byte)buff[(i<<2)+1];
serial[7-i]=(serial[7-i]<<8)+(byte)buff[(i<<2)+2];
serial[7-i]=(serial[7-i]<<8)+(byte)buff[(i<<2)+3];
}
serial[7]=(serial[1]+serial[2]+serial[3]+serial[4])^serial[7];
serial[6]=(serial[0]+serial[5])^serial[6];
m_Edit2.Format ("%08lX",serial[0]);m_Edit2+='-';
sprintf(buff,"%08lX",serial[1]);m_Edit2+=buff;m_Edit2+='-';
sprintf(buff,"%08lX",serial[2]);m_Edit2+=buff;m_Edit2+='-';
sprintf(buff,"%08lX",serial[3]);m_Edit2+=buff;m_Edit2+='-';
sprintf(buff,"%08lX",serial[4]);m_Edit2+=buff;m_Edit2+='-';
sprintf(buff,"%08lX",serial[5]);m_Edit2+=buff;m_Edit2+='-';
sprintf(buff,"%08lX",serial[6]);m_Edit2+=buff;m_Edit2+='-';
sprintf(buff,"%08lX",serial[7]);m_Edit2+=buff;
UpdateData(false);
}
--------------------------------------------------------------------------------
【对比另一个类似程序】
在调试这个软件的同时我也调试过另一个视频剪接软件All Video Splitter,不同的是用了 rsa1024 ,两个程序也有了不一样的命运。
004B126B |. BA 60164B00 MOV EDX,videospl.004B1660 ; ASCII ".DEFAULT\Software\Zealotsoft\All Video Splitter"
004B1270 |. 8BC3 MOV EAX,EBX
004B1272 |. E8 C17EF8FF CALL videospl.00439138
004B1277 |. 84C0 TEST AL,AL
004B1279 |. 0F84 B1020000 JE videospl.004B1530
004B127F |. E8 D8FAFFFF CALL videospl.004B0D5C ; read username & regcode
004B1284 |. A1 543E4B00 MOV EAX,DWORD PTR DS:[4B3E54]
004B1289 |. 8338 00 CMP DWORD PTR DS:[EAX],0
004B128C |. 0F84 EE000000 JE videospl.004B1380 ; if(strlen(username)==0) return false
004B1292 |. A1 F43E4B00 MOV EAX,DWORD PTR DS:[4B3EF4]
004B1297 |. 8338 00 CMP DWORD PTR DS:[EAX],0
004B129A |. 0F84 E0000000 JE videospl.004B1380 ; if(strlen(regcode)==0) return false
004B12A0 |. B8 645D4B00 MOV EAX,videospl.004B5D64
004B12A5 |. 8B15 F43E4B00 MOV EDX,DWORD PTR DS:[4B3EF4] ; videospl.004B5CD8
004B12AB |. 8B12 MOV EDX,DWORD PTR DS:[EDX]
004B12AD |. E8 DE2EF5FF CALL videospl.00404190
004B12B2 |. BA 485D4B00 MOV EDX,videospl.004B5D48
004B12B7 |. A1 645D4B00 MOV EAX,DWORD PTR DS:[4B5D64]
004B12BC |. E8 1FCDFFFF CALL videospl.004ADFE0 : 跟进,跟进代码在后面
004B12C1 |. B8 645D4B00 MOV EAX,videospl.004B5D64
004B12C6 |. E8 712EF5FF CALL videospl.0040413C
004B12CB |. 8D55 E8 LEA EDX,DWORD PTR SS:[EBP-18]
004B12CE |. A1 9C3E4B00 MOV EAX,DWORD PTR DS:[4B3E9C]
004B12D3 |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B12D5 |. 8B80 38030000 MOV EAX,DWORD PTR DS:[EAX+338]
004B12DB |. E8 1CFEFAFF CALL videospl.004610FC ; 取得 e:65537 即 0x10001
004B12E0 |. 8B45 E8 MOV EAX,DWORD PTR SS:[EBP-18]
004B12E3 |. 8D55 EC LEA EDX,DWORD PTR SS:[EBP-14]
004B12E6 |. E8 D572F5FF CALL videospl.004085C0
004B12EB |. 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14]
004B12EE |. BA 4C5D4B00 MOV EDX,videospl.004B5D4C
004B12F3 |. E8 DCD0FFFF CALL videospl.004AE3D4 ; 将 e 转为大数
004B12F8 |. 8D55 E0 LEA EDX,DWORD PTR SS:[EBP-20]
004B12FB |. A1 9C3E4B00 MOV EAX,DWORD PTR DS:[4B3E9C]
004B1300 |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B1302 |. 8B80 3C030000 MOV EAX,DWORD PTR DS:[EAX+33C]
004B1308 |. E8 EFFDFAFF CALL videospl.004610FC ; 取模 n:6433969951……985573
004B130D |. 8B45 E0 MOV EAX,DWORD PTR SS:[EBP-20]
004B1310 |. 8D55 E4 LEA EDX,DWORD PTR SS:[EBP-1C]
004B1313 |. E8 A872F5FF CALL videospl.004085C0
004B1318 |. 8B45 E4 MOV EAX,DWORD PTR SS:[EBP-1C]
004B131B |. BA 545D4B00 MOV EDX,videospl.004B5D54
004B1320 |. E8 AFD0FFFF CALL videospl.004AE3D4 ; 将 n 转为大数
004B1325 |. 68 5C5D4B00 PUSH videospl.004B5D5C
004B132A |. 68 5C5D4B00 PUSH videospl.004B5D5C
004B132F |. 68 5C5D4B00 PUSH videospl.004B5D5C
004B1334 |. 68 5C5D4B00 PUSH videospl.004B5D5C
004B1339 |. 68 645D4B00 PUSH videospl.004B5D64
004B133E |. B9 545D4B00 MOV ECX,videospl.004B5D54
004B1343 |. BA 4C5D4B00 MOV EDX,videospl.004B5D4C
004B1348 |. A1 485D4B00 MOV EAX,DWORD PTR DS:[4B5D48]
004B134D |. E8 E6F4FFFF CALL videospl.004B0838 ; rsa_de( )
004B1352 |. A1 F43E4B00 MOV EAX,DWORD PTR DS:[4B3EF4]
004B1357 |. 8B15 645D4B00 MOV EDX,DWORD PTR DS:[4B5D64]
004B135D |. E8 2E2EF5FF CALL videospl.00404190
004B1362 |. B8 4C5D4B00 MOV EAX,videospl.004B5D4C
004B1367 |. E8 E0D2FFFF CALL videospl.004AE64C
004B136C |. B8 545D4B00 MOV EAX,videospl.004B5D54
004B1371 |. E8 D6D2FFFF CALL videospl.004AE64C
004B1376 |. B8 5C5D4B00 MOV EAX,videospl.004B5D5C
004B137B |. E8 CCD2FFFF CALL videospl.004AE64C
004B1380 |> A1 543E4B00 MOV EAX,DWORD PTR DS:[4B3E54]
004B1385 |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B1387 |. 8B15 F43E4B00 MOV EDX,DWORD PTR DS:[4B3EF4] ; videospl.004B5CD8
004B138D |. 8B12 MOV EDX,DWORD PTR DS:[EDX]
004B138F |. E8 B431F5FF CALL videospl.00404548 ; rsa 的结果跟用户名比较
004B1394 |. 75 2D JNZ SHORT videospl.004B13C3
004B1396 |. A1 A0424B00 MOV EAX,DWORD PTR DS:[4B42A0]
004B139B |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B139D |. 8B80 44030000 MOV EAX,DWORD PTR DS:[EAX+344]
004B13A3 |. 33D2 XOR EDX,EDX
004B13A5 |. 8B08 MOV ECX,DWORD PTR DS:[EAX]
004B13A7 |. FF51 64 CALL DWORD PTR DS:[ECX+64]
004B13AA |. A1 A0424B00 MOV EAX,DWORD PTR DS:[4B42A0]
004B13AF |. 8B00 MOV EAX,DWORD PTR DS:[EAX]
004B13B1 |. 8B80 50030000 MOV EAX,DWORD PTR DS:[EAX+350]
004B13B7 |. 33D2 XOR EDX,EDX
004B13B9 |. 8B08 MOV ECX,DWORD PTR DS:[EAX]
004B13BB |. FF51 64 CALL DWORD PTR DS:[ECX+64]
004B13BE |. E9 0D020000 JMP videospl.004B15D0
004B13C3 |> 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
004B13C6 |. BA 98164B00 MOV EDX,videospl.004B1698 ; ASCII "UserDate"
004B13CB |. 8BC3 MOV EAX,EBX
004B13CD |. E8 2E7FF8FF CALL videospl.00439300
004B12BC CALL videospl.004ADFE0 的跟进代码:
004AE03E |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
004AE041 |. E8 B663F5FF CALL videospl.004043FC ; strlen(regcode),作为下面循环次数
004AE046 |. 8BD8 MOV EBX,EAX
004AE048 |. 85DB TEST EBX,EBX
004AE04A |. 7E 20 JLE SHORT videospl.004AE06C
004AE04C |. BE 01000000 MOV ESI,1
004AE051 |> 8D45 F8 /LEA EAX,DWORD PTR SS:[EBP-8]
004AE054 |. 8B55 FC |MOV EDX,DWORD PTR SS:[EBP-4] ; read regcode
004AE057 |. 0FB65432 FF |MOVZX EDX,BYTE PTR DS:[EDX+ESI-1] ; regcode[i]
004AE05C |. 8B9495 F4FBFF>|MOV EDX,DWORD PTR SS:[EBP+EDX*4-4>; 根据regcode[i]查替换表得6位的二进制字符串
004AE063 |. E8 9C63F5FF |CALL videospl.00404404 ; strcat( )
004AE068 |. 46 |INC ESI ; i + 1
004AE069 |. 4B |DEC EBX ; 循环次数减 1
004AE06A |.^ 75 E5 \JNZ SHORT videospl.004AE051
替换表在堆栈窗口可以看到:
0012FBEC 01165088 ASCII "111110" ; +
0012FBF0 00000000
0012FBF4 00000000
0012FBF8 00000000
0012FBFC 00000000
0012FC00 01164FC0 ASCII "110100" ; 0
0012FC04 01164FD4 ASCII "110101" ; 1
0012FC08 01164FE8 ASCII "110110" ; 2
0012FC0C 01164FFC ASCII "110111" ; 3
0012FC10 01165010 ASCII "111000" ; 4
0012FC14 01165024 ASCII "111001" ; 5
0012FC18 01165038 ASCII "111010" ; 6
0012FC1C 0116504C ASCII "111011" ; 7
0012FC20 01165060 ASCII "111100" ; 8
0012FC24 01165074 ASCII "111101" ; 9
0012FC28 00000000
0012FC2C 00000000
0012FC30 00000000
0012FC34 0116509C ASCII "111111" ; =
0012FC38 00000000
0012FC3C 00000000
0012FC40 00000000
0012FC44 01160234 ASCII "000001" ; A
0012FC48 0115DAF0 ASCII "000011" ; B
0012FC4C 01161F28 ASCII "000101" ; C
0012FC50 01164C3C ASCII "000111" ; D
………………
……………… 依次加 2
………………
0012FCA0 01164F5C ASCII "101111" ; X
0012FCA4 01164F84 ASCII "110001" ; Y
0012FCA8 01164FAC ASCII "110011" ; Z
0012FCAC 00000000
0012FCB0 00000000
0012FCB4 00000000
0012FCB8 00000000
0012FCBC 00000000
0012FCC0 00000000
0012FCC4 01162F88 ASCII "000000" ; a
0012FCC8 01149CFC ASCII "000010" ; b
0012FCCC 01161F14 ASCII "000100" ; c
0012FCD0 01164C28 ASCII "000110" ; d
0012FCD4 01164C50 ASCII "001000" ; e
………………
……………… 依次加 2
………………
0012FD20 01164F48 ASCII "101110" ; x
0012FD24 01164F70 ASCII "110000" ; y
0012FD28 01164F98 ASCII "110010" ; z
004AE06C |> 8BC7 MOV EAX,EDI
004AE06E |. E8 C960F5FF CALL videospl.0040413C
004AE073 |. 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
004AE076 |. E8 8163F5FF CALL videospl.004043FC ; strcat( ) 结果的长度
004AE07B |. 85C0 TEST EAX,EAX
004AE07D |. 79 03 JNS SHORT videospl.004AE082
004AE07F |. 83C0 07 ADD EAX,7 ; if(strlen()==0) strlen()=7
004AE082 |> C1F8 03 SAR EAX,3 ; strlen()/8 作为下面的循环次数
004AE085 |. 8BD8 MOV EBX,EAX
004AE087 |. 85DB TEST EBX,EBX
004AE089 |. 7E 57 JLE SHORT videospl.004AE0E2
004AE08B |> 8D85 F0FBFFFF /LEA EAX,DWORD PTR SS:[EBP-410]
004AE091 |. 50 |PUSH EAX
004AE092 |. B9 08000000 |MOV ECX,8
004AE097 |. BA 01000000 |MOV EDX,1
004AE09C |. 8B45 F8 |MOV EAX,DWORD PTR SS:[EBP-8] ; char *pstr 指针最初指向上面strcat( )的结果
004AE09F |. E8 B865F5FF |CALL videospl.0040465C ; 从 pstr 指针处取 8 个字符
004AE0A4 |. 8B95 F0FBFFFF |MOV EDX,DWORD PTR SS:[EBP-410]
004AE0AA |. 8D45 F7 |LEA EAX,DWORD PTR SS:[EBP-9]
004AE0AD |. E8 AAFBFFFF |CALL videospl.004ADC5C ; 转成数值,得到一个byte
004AE0B2 |. 8D85 ECFBFFFF |LEA EAX,DWORD PTR SS:[EBP-414]
004AE0B8 |. 8A55 F7 |MOV DL,BYTE PTR SS:[EBP-9]
004AE0BB |. E8 6462F5FF |CALL videospl.00404324
004AE0C0 |. 8B95 ECFBFFFF |MOV EDX,DWORD PTR SS:[EBP-414]
004AE0C6 |. 8BC7 |MOV EAX,EDI
004AE0C8 |. E8 3763F5FF |CALL videospl.00404404 ; 将每轮循环中得到的 byte 拼成字节串
004AE0CD |. 8D45 F8 |LEA EAX,DWORD PTR SS:[EBP-8]
004AE0D0 |. B9 08000000 |MOV ECX,8
004AE0D5 |. BA 01000000 |MOV EDX,1
004AE0DA |. E8 BD65F5FF |CALL videospl.0040469C ; pstr + 8
004AE0DF |. 4B |DEC EBX
004AE0E0 |.^ 75 A9 \JNZ SHORT videospl.004AE08B
004AE0E2 |> 33C0 XOR EAX,EAX
004AE0E4 |. 5A POP EDX
004AE0E5 |. 59 POP ECX
004AE0E6 |. 59 POP ECX
程序首先将注册码中的每一个字符替换成'0'、'1'组成的六位字符串,然后每八个转成一个byte,连接后作待加密信息。
比如,输入假码:9876543321abcd
程序首先查表替换成:"111101 111100 111011 111010 111000 111001 110111 110110 110101 000000 000010 000100 000110"
然后每八个分组:"11110111 11001110 11111010 11100011 10011101 11110110 11010100 00000000 10000100 000110"
十六进制就是:F7 CE FA E7 8D F6 D4 00 84 最后还多一些不足 8 位的就舍去,这个进行 rsa 计算结果等于 username就通过。
如果要作注册机就必须多模数 n 因式分解,再看看n:
10进制:64339699515705192068194993623307081615062638322012232511872724556480843761749970481781239168889774406854078190595474311516630418546131048058995412744169522448609743655131377088569993438211545658975497514074789487215208702967896731510271633140995521267487600450311206985573
HEX:
79C99D3C3FAF7FF633A11AC06DB700D5B0A93ED27F641C66A9DCEFBE9E679ACB0EE67791C742313BD7A71A10028AFB28661757BF2816DBF1CC000076247DCD371179C831E10887F4AC34C96C5448C83702668432FEA31B5DC6C938D8EAB27B68A7B5065787A02632C3817B7C9E71DFDF65
rsa_tools II 测试数据达到903位,因式分解式不可能了。程序只能爆破,程序有四处地方拿 rsa 结果跟 username 比较:
1、启动程序时;2、打开关于对话框时;3、打开注册对话框时;4、关闭程序时;5、打开视频文件及添加水印时;
如果一一修改比较麻烦,程序并不进行多次的 rsa 运算,rsa会拖掉程序的运行速度,每次比较都是调用的同一个rsa的运算结果,我们就在第一次rsa运算后,比较前修改rsa的运算结果
找到这个地方修改:
004B1387 |. 8B15 F43E4B00 MOV EDX,DWORD PTR DS:[4B3EF4] ; videospl.004B5CD8
004B138D |. 8B12 MOV EDX,DWORD PTR DS:[EDX]
004B138F |. E8 B431F5FF CALL videospl.00404548 ; rsa 的结果跟用户名比较,patch
004B1394 |. 75 2D JNZ SHORT videospl.004B13C3
004B1396 |. A1 A0424B00 MOV EAX,DWORD PTR DS:[4B42A0]
以上代码改为:
004B1387 . 8B15 F43E4B00 MOV EDX,DWORD PTR DS:[4B3EF4] ; videospl.004B5CD8
004B138D . 8B12 MOV EDX,DWORD PTR DS:[EDX]
004B138F . E9 6C090000 JMP videospl.004B1D00 ; patch,不用比了,直接跳到自己的代码
004B1394 . 75 2D JNZ SHORT videospl.004B13C3
004B1396 > A1 A0424B00 MOV EAX,DWORD PTR DS:[4B42A0]
………………
004B1D00 > \60 PUSHAD ; 保护现场
004B1D01 . 8B48 FC MOV ECX,DWORD PTR DS:[EAX-4]
004B1D04 . 894A FC MOV DWORD PTR DS:[EDX-4],ECX ; 取用户名长度
004B1D07 . 85C9 TEST ECX,ECX
004B1D09 . 74 0A JE SHORT videospl.004B1D15
004B1D0B . 8BFA MOV EDI,EDX ; usename
004B1D0D . 8BF0 MOV ESI,EAX ; rsa_result
004B1D0F . FC CLD
004B1D10 . F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR>; 字符串传送
004B1D12 . C607 00 MOV BYTE PTR DS:[EDI],0 ; 字符串结束标志
004B1D15 > 61 POPAD ; 恢复现场
004B1D16 .^ E9 7BF6FFFF JMP videospl.004B1396 ; 跳回去执行原来的代码,不好意思,来比较都省了,看下堆栈,没有问题,^_^
最后不要忘记在程序文件夹中建立一个文件 xxxx.ini,xxxx跟程序文件名相同,里面写上自己的名字和任意注册码:
[Options]
User=rdsnow[BCG][PYG][D.4s]
Pass=98764321abcd
测试程序,变成了注册版,剪接的视频也没有了水印,看来是完美爆破了,看到论坛上有用替换模数 n 的方法破解,但是反正要改程序,我就直接爆了。
--------------------------------------------------------------------------------
【破解心得】
同样是使用 rsa 加密程序,但是两个程序都有缺陷
第一个程序被写出了注册机模是因为数太短,现在256位大数的因式分解用时不到1小时,失去了使用rsa的意义。
第二个程序虽然用了 rsa1024,但是却在程序的校验上做的不够,让人随意修改他的代码,关键代码要着重保护。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年04月07日 18:24:48
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课