某屏幕录像软件的注册算法分析
(编辑:jimmy 日期: 2024/11/15 浏览:3 次 )
前言 : 我在破解完这个屏幕录像专家的注册算法后想分享一下我的思路和大家一起学习一下,但是我不知道这是否违规所以在论坛上搜了一下原来以前已经有几个大佬分析过这个软件了,分析的确实好条理清晰。我是新手,所以我主要是站在新手的角度详细说一下软件的破解思路(和那几位大佬自然不能比),我始终认为只有站在菜鸟的立场去分析软件才能把文章写的通俗易懂。(但是这次我最后分析的并不好,前面思路还算清晰大家可以看文章最后链接那位大佬的贴子,我的帖子就给他打打辅助吧(估计也不配哈哈))
20200220133124.png
点击确定后其会弹出:注册失败,请检查输入是否有误的窗口。
20200220133041.png
我们熟悉了程序后就开始正式开始破解他吧!
20200220142518.png
2. 然后我们直接将程序载入OD分析
因为程序注册失败会弹出时注册失败的窗口
① 我先是从弹出失败窗口处下手(目的是想寻找调用弹出失败窗口的代码从而寻找关键判断),但是发现下了API断点后回溯寻找不到关键代码
② 那我们就换一条思路下个确定按钮事件断点(目的是为了寻找关键代码),但是发现点击确定按钮后断不下来。
③ 不这么花里胡哨的了直接搜索失败信息的字符串算了:“注册失败,请检查你的输入是否有误!”。(其实一般都是先搜索字符串,我只是想练一下①②这两种思路,如果我们在分析软件的时候应该先用③不行在试试①②)
20200220150345.png
我们双击此字符串后进入关键代码处并在函数头部下断点我们,然后我们随便输入用户名(88888888)和假的序列号(23h4j8skeros9fg458)后点击确定
程序会停在此函数头部。
MJ8AFTW[0WFA9KZ]U~(AD0B.png
我们F8单步向下分析程序,到达关键判断处。其在调用完call 0x4135A4后(返回值为eax)
发现如果eax的值小于50则会弹出注册失败的窗口。
5%(U_}H2}%F%{RQ)DGRLVB5.png
我们在call 004135A4处下断点,然后我们运行程序F7进入此call后进行分析。
其是先判断 0x0019E7B8地址处的值是否为0,如果为0则返回eax为0,否则返回 eax = [ [ 0x0019e7b8 ] ] - 4
G~)_X`XYEE74C{GL}7TUS0G.png
我们在堆栈窗口中搜索0x19e7b8,发现其值为一个字符串的地址。(0x19e7b8应该是一个指针变量)
BE9`OA`W2_F]_JZC@BGJ]]C.png
eax返回值[ [0x19e7b8] ]- 4 等于8 ( 正好为此字符串的长度8),我们需要知道此字符串是怎么产生的。
7}B4Q@0X~XPVMJI0~}1IKE2.png
我们重新运行程序F8往下分析发现此字符串生成的关键算法。即把我们输入的序列号中的数字提取成此字符串且数字的个数最多为0x400个。
XTCPFSZ4GEI9_F`1P}KO.png
因为此字符串的长度为关键判断函数的返回值eax,所以我们输入的序列号中的数字的个数不能小于50。(小于50就会弹出注册失败窗口)
然后我们运行程序,更改我们输入的序列号为“12345678912345678912345678912345678912345678912345”(50个数字)点击确定后运行到跳转处。
其会执行跳转不会弹出注册失败窗口,我们F8继续往下分析
1YB3G]M]{)S`HK6[GYJ7D25.png
我们F8继续往下执行有到达关键跳转处,当[ebp - 0xd8] != [ebp - 0xc0]时会弹出注册失败窗口,
而[ebp - 0xd8] 和 [ebp - 0xc0]这两个值分别是函数call 0x00492000 的返回值的后16位 和 函数call 0x005d5b80的返回值
(第一个函数的返回值后16位为0x8101,第二个函数的返回值为0x3039)
I)B8LH7FM4_U]7OVKBXM)(V.png
我们分别进入两个函数分析其返回值生成算法,在二者调用处下断点,运行程序到第一个函数调用处F7进入函数
此函数是将序列号的前45个字符经过此算法处理后返回产生一个32位的数值然后充当返回值。
{KL{9M66(`ZAI%]2CFD8O)7.png
接着我们运行程序来到第二个关键函数处,F7进入此函数后我们发现当执行完call 0x005b6202后返回值eax(0x3060)已经产生,
所以此函数的eax返回值时实际是call 0x005b6202函数产生的,
3(PPOR_T$[HD%%WQJX}@E.png
我们在此函数入口处下断点运行程序来到此处后,再F7进入此函数后发现当执行完call 0x005bd528后eax返回值(0x3060)已经产生,
所以此函数的返回值是call 0x005bd528函数后产生的,
RK8(J_`@}%IJ7TI5)QR~_LA.png
所以我们接着在此函数处下断点运行程序来到此处F7进入发现其代码逻辑:
服了原来就是c语言函数atof( )eax是参数,而eax刚好指向我们输入的序列号的后五位(代码我就不贴了,其实就是atof函数)
所以第二个关键函数就是调用了atof( )函数,返回我们输入序列号后五位所表示的十进制数值。
Q34~`Z9DQ~RO9E5D2@59921.png
我们把这两个关键函数都分析了可以写出程序产生一个能够让 第一个关键函数返回值的后16位 == 第二个关键函数返回值的序列号
这里我就粘贴写的程序了,直接给出一个能满足上述条件的序列号:“61792262536446053268598766557788952812559488517686”
我们运行程序重新输入序列号后运行程序其执行了跳转( 不会弹出注册失败 )。
D_)1_I(MLB1I(V40$[PX2$S.png
然后我们接着F8向下分析发现关键跳转处: 我们不用先不用管其内部的处理算法,只要看其宏观上的逻辑
其就是在比较 edx所指向的5个数据 是否 等于edi所指向的5个字符,如果有一个不等于其都会跳转到失败
那么我们就要知道这5个数据 和 这5个字符是怎么产生的。
[Asm] 纯文本查看 复制代码
004A111A . 8985 18FFFFFF mov dword ptr ss:[ebp-0xE8],eax004A1120 . 8DB5 00FFFFFF lea esi,dword ptr ss:[ebp-0x100]004A1126 . 33DB xor ebx,ebx ; ebx = 0004A1128 > 8B95 18FFFFFF mov edx,dword ptr ss:[ebp-0xE8] ; do{004A112E . 0FBE06 movsx eax,byte ptr ds:[esi] ; esi指向一个含有5个字符的字符串004A1131 . 0FBE0A movsx ecx,byte ptr ds:[edx] ; edx指向5个数据004A1134 . 83C1 EC add ecx,-0x14 ; ecx = ecx - 0x14004A1137 . 3BC1 cmp eax,ecx004A1139 . 0F85 80000000 jnz 屏录专家.004A11BF ; if(eax == ecx)004A113F . 83FB 03 cmp ebx,0x3 ; {004A1142 . 75 6A jnz X屏录专家.004A11AE ; if(ebx == 3)004A1144 . 81C7 444D0000 add edi,0x4D44 ; {004A114A . 89BD A0F6FFFF mov dword ptr ss:[ebp-0x960],edi ; edi = edi + 0x4d44004A1150 . DB85 A0F6FFFF fild dword ptr ss:[ebp-0x960] ; st = edi * 3.14004A1156 . DC0D 58194A00 fmul qword ptr ds:[0x4A1958] ; st = st * 0.1594896331738427110004A115C . DB2D 60194A00 fld tbyte ptr ds:[0x4A1960]004A1162 . DEC9 fmulp st(1),st004A1164 . E8 5FCA1200 call 屏录专家.005CDBC8 ; eax = int(st)004A1169 . 8BF8 mov edi,eax ; edi = eax004A116B . 8BC7 mov eax,edi004A116D . B9 A0860100 mov ecx,0x186A0 ; ecx = 0x186a0004A1172 . 99 cdq004A1173 . F7F9 idiv ecx ; edx:eax = eax / ecx004A1175 . 8BFA mov edi,edx ; - edi = edx004A1177 . 33C0 xor eax,eax ; eax = 0004A1179 . 8985 3CFFFFFF mov dword ptr ss:[ebp-0xC4],eax ; [ebp - 0xc4] = 0004A117F . 33D2 xor edx,edx ; edx =0004A1181 . 8D85 A4FEFFFF lea eax,dword ptr ss:[ebp-0x15C]004A1187 > 0FBE08 movsx ecx,byte ptr ds:[eax] ; 把那20个字符的前19个累加到 [ebp - 0xc4]004A118A . 018D 3CFFFFFF add dword ptr ss:[ebp-0xC4],ecx004A1190 . 42 inc edx004A1191 . 40 inc eax004A1192 . 83FA 13 cmp edx,0x13004A1195 .^ 7C F0 jl X屏录专家.004A1187004A1197 . 8B85 3CFFFFFF mov eax,dword ptr ss:[ebp-0xC4] ; eax = [ebp - 0xc4]004A119D . B9 0A000000 mov ecx,0xA ; ecx = 0xa004A11A2 . 99 cdq004A11A3 . F7F9 idiv ecx ; edx:eax = eax / ecx004A11A5 . 83C2 30 add edx,0x30 ; edx = edx + 0x30004A11A8 . 8995 3CFFFFFF mov dword ptr ss:[ebp-0xC4],edx ; [ebp - 0xc4] = edx004A11AE > 43 inc ebx ; }004A11AF . FF85 18FFFFFF inc dword ptr ss:[ebp-0xE8]004A11B5 . 46 inc esi ; ebx++004A11B6 . 83FB 05 cmp ebx,0x5 ; esi++004A11B9 .^ 0F8C 69FFFFFF jl 屏录专家.004A1128 ; }while(ebx < 5)004A11BF > 83FB 05 cmp ebx,0x5004A11C2 . 0F8C BE060000 jl 屏录专家.004A1886 ; 不能跳(跳转就失败)
下面我们就先来分析那5个数据是怎么产生的吧,edx指向那5个数据,edx值为0x0019e668
SX0FO}($K1M]724LQ~OO_{B.png
我们带数据窗口中找到搜索0x0019e668,然后我们对此处的内存下内存写入断点,再次运行程序程序会停在其产生的地方。
我们发现这5个数据实际是送地址0x05103110地址处复制过来的20个字符之中的前5字符。那我们就需要跟踪看0x05103110地址处的数据是怎么产生的
}1I`}Q]TM@_ZWMN]BK}AIC5.png
方法和上面一样我们在数据窗口中搜索0x05103110然后对此处的20个字符下内存写入断点,再次运行程序其会停在其产生处。
我们发现0x05103110地址处的20个字符是从地址0x0019dda4(0x0019b4 - 0x10)处传送来的
L]D7P(N3_T@M9%N{HGDX25D.png
那好我们接着用上述方法在数据窗口中搜索0x0019dda4然后对此处的20个字符下内存写入断点(这里注意要把上面我们对0x05103110处下的内存写入断点删除)
运行程序,程序会停在其产生处。但是我们发现其会先对此处内存清0(此时程序肯定会停止,我们只需继续运行)。
然后我们发现其会将我们输入的序列号的前40个字符复制到这块内存中。
2GGNW}N5UQ2[L4YY}GE0OTF.png
其复制完之后我们继续点击运行其又会停止,我们分析此处代码的算法。
的出我们追踪的此20个字符产生的算法是:先把我们输入的序列号的前40个字符的第3个和第39个,第5个和第26个,第10个和第32个字符分别互换后,
再每两个字符一组转化为其对应的十进制数值 + 9 + ebx/2得到的值挨边存到我们追踪的那块内存中,循环20次(ebx是计数器)。
M3)ZRUMTF(39XTK}Q%TP4.png
我们知道这20个字符是如何产生的之后我们在去看那与这20个字符的前5个数据比较的 那另外5个字符是怎么产生的。(别忘取消所有的内存写入断点)
我们运行到原来的判断处发现此五个字符的地址为0x0019e6c4,
IY0O)E43)(HA6~TM]HD0_XI.png
同样我们在数据窗口对此地址的内存下内存写入断点,运行程序后其会停在其产生处。
我们发现那5个字符实际是 我们的变换后的机器码的前20位(3位和19位,5位和16位,9位和12位互换。)的每一位
和我们的用户名的每一位进行异或后产生的值累加后 + 0x3039 -----》得到的值转化为对应的字符(即调用itoa函数)。
DPCO9$L0VX28QAGDWJY1NV4.png
现在知道了那20个字符的前5个数据产生的算法,以及与其比较的5个字符的产生算法了。(其需要对应相等才能不弹出注册失败)
因为这五个字符是用户名和变换后的机器码产生的,又因为这5个数据是我们输入的序列号的前10个两两一组产生的,
所以我们由用户名和注册码就可以唯一确定正确序列号的前10个字符了。
然后由下面的算法我们又能确定第11位和第12位字符。我们确定了前12位字符,然后我们随机生成后面的38位字符组成50个字符的序列号后。
由下面算法得最后两个字符还得满足一定条件才能成功。
[Asm] 纯文本查看 复制代码
004A1126 . 33DB xor ebx,ebx ; ebx = 0004A1128 > 8B95 18FFFFFF mov edx,dword ptr ss:[ebp-0xE8] ; do{004A112E . 0FBE06 movsx eax,byte ptr ds:[esi] ; esi指向一个含有5个字符的字符串004A1131 . 0FBE0A movsx ecx,byte ptr ds:[edx] ; edx指向一个含有20个字符的字符串004A1134 . 83C1 EC add ecx,-0x14 ; ecx = ecx - 0x14004A1137 . 3BC1 cmp eax,ecx004A1139 . 0F85 80000000 jnz 屏录专家.004A11BF ; if(eax == ecx)004A113F . 83FB 03 cmp ebx,0x3 ; {004A1142 . 75 6A jnz X屏录专家.004A11AE ; if(ebx == 3)004A1144 . 81C7 444D0000 add edi,0x4D44 ; {004A114A . 89BD A0F6FFFF mov dword ptr ss:[ebp-0x960],edi ; edi = edi + 0x4d44004A1150 . DB85 A0F6FFFF fild dword ptr ss:[ebp-0x960] ; st = edi * 3.14004A1156 . DC0D 58194A00 fmul qword ptr ds:[0x4A1958] ; st = st * 0.1594896331738427110004A115C . DB2D 60194A00 fld tbyte ptr ds:[0x4A1960]004A1162 . DEC9 fmulp st(1),st004A1164 . E8 5FCA1200 call 屏录专家.005CDBC8 ; eax = int(st)004A1169 . 8BF8 mov edi,eax ; edi = eax004A116B . 8BC7 mov eax,edi004A116D . B9 A0860100 mov ecx,0x186A0 ; ecx = 0x186a0004A1172 . 99 cdq004A1173 . F7F9 idiv ecx ; edx:eax = eax / ecx004A1175 . 8BFA mov edi,edx ; - edi = edx004A1177 . 33C0 xor eax,eax ; eax = 0004A1179 . 8985 3CFFFFFF mov dword ptr ss:[ebp-0xC4],eax ; [ebp - 0xc4] = 0004A117F . 33D2 xor edx,edx ; edx =0004A1181 . 8D85 A4FEFFFF lea eax,dword ptr ss:[ebp-0x15C]004A1187 > 0FBE08 movsx ecx,byte ptr ds:[eax] ; 把那20个字符的前19个累加到 [ebp - 0xc4]004A118A . 018D 3CFFFFFF add dword ptr ss:[ebp-0xC4],ecx004A1190 . 42 inc edx004A1191 . 40 inc eax004A1192 . 83FA 13 cmp edx,0x13004A1195 .^ 7C F0 jl X屏录专家.004A1187004A1197 . 8B85 3CFFFFFF mov eax,dword ptr ss:[ebp-0xC4] ; eax = [ebp - 0xc4]004A119D . B9 0A000000 mov ecx,0xA ; ecx = 0xa004A11A2 . 99 cdq004A11A3 . F7F9 idiv ecx ; edx:eax = eax / ecx004A11A5 . 83C2 30 add edx,0x30 ; edx = edx + 0x30004A11A8 . 8995 3CFFFFFF mov dword ptr ss:[ebp-0xC4],edx ; [ebp - 0xc4] = edx004A11AE > 43 inc ebx ; }004A11AF . FF85 18FFFFFF inc dword ptr ss:[ebp-0xE8]004A11B5 . 46 inc esi ; ebx++004A11B6 . 83FB 05 cmp ebx,0x5 ; esi++004A11B9 .^ 0F8C 69FFFFFF jl 屏录专家.004A1128 ; }while(ebx < 5)004A11BF > 83FB 05 cmp ebx,0x5004A11C2 . 0F8C BE060000 jl 屏录专家.004A1886 ; 不能跳(跳转就失败)004A11C8 . 0FBE85 B7FEFF>movsx eax,byte ptr ss:[ebp-0x149] ; 看那20个字符的最后一个字符是不是等于[ebp - 0xc4]004A11CF . 3B85 3CFFFFFF cmp eax,dword ptr ss:[ebp-0xC4]004A11D5 . 74 09 je X屏录专家.004A11E0 ; 或者最后一个字符大于等于0x41004A11D7 . 83F8 41 cmp eax,0x41004A11DA . 0F8C A6060000 jl 屏录专家.004A1886 ; 不能跳(跳转就失败)004A11E0 > 8BC7 mov eax,edi ; eax = edi004A11E2 . B9 0A000000 mov ecx,0xA ; ecx = 0xa004A11E7 . 99 cdq004A11E8 . F7F9 idiv ecx ; edx = eax % ecx004A11EA . 0FBE841D A4FE>movsx eax,byte ptr ss:[ebp+ebx-0x15C] ; eax = 第6个字符004A11F2 . 83C0 BF add eax,-0x41 ; eax = eax - 0x41004A11F5 . 2BC2 sub eax,edx ; eax = eax - edx004A11F7 . 8985 40FFFFFF mov dword ptr ss:[ebp-0xC0],eax004A11FD . 83BD 40FFFFFF>cmp dword ptr ss:[ebp-0xC0],0x0 ; if(eax == 0 || eax == 9)004A1204 . 74 0D je X屏录专家.004A1213 ; 成功004A1206 . 83BD 40FFFFFF>cmp dword ptr ss:[ebp-0xC0],0x9 ; else004A120D . 0F85 EC050000 jnz 屏录专家.004A17FF ; 其跳转就失败004A1213 > 66:C785 5CFFF>mov word ptr ss:[ebp-0xA4],0x104004A121C . BA 5CCF6200 mov edx,屏录专家.0062CF5C004A1221 . 8D45 B4 lea eax,dword ptr ss:[ebp-0x4C]004A1224 . E8 9B411300 call 屏录专家.005D53C4004A1229 . FF85 68FFFFFF inc dword ptr ss:[ebp-0x98]004A122F . 8B00 mov eax,dword ptr ds:[eax]004A1231 . E8 3E4B0E00 call 屏录专家.00585D74 ; 成功
最后的满足条件序列号的算法描述我写的一点都不好,我发现我这分析越写越乱,哎!和大佬没法比。
(主要是这个软件的算法最后满足的条件并不好理解,我也不好描述,大家可以看看aikuimail大佬的分析! 条例清晰真是太nb了)
我的注册机我的太low了产生序列号满算法没优化大家最好不要看(辣眼睛!),大家有需要就在下面那位大佬的帖子上下载就好了!
XXXX专家2015算法分析及注册机编写
https://www.52pojie.cn/thread-454940-1-1.html
(出处: 吾爱破解论坛)
我的注册机:注册机代码.txt
下一篇:某某云网络验证脱壳