好友
阅读权限10
听众
最后登录1970-1-1
|
本帖最后由 15788888 于 2024-11-26 20:19 编辑
本人刚刚入门汇编逆向破解分析,本帖将记录我对160个CrackMe程序中的第005程序的分析过程。在学习的过程中,我会边学边记录。如果有不正确之处,还请各位指正。
程序打开后有一个文本框和一个图片框在进行轮播图片还有一个注册按钮,右边文本是作者给的介绍和提示。
查了一下壳是upx的压缩壳,先用通用脱壳机进行脱壳。
还是查找字符串,看一下有没有有用的字符,通过搜索字符串我们看到了 "注册了" 这个位置 我们进去看一下。
可以看到上面有5个跳转,我们要让代码能顺利走到字符串 “注册了” 这个位置才能注册成功 所以先把这5个跳转全部nop试一下
nop掉之后 爆破就成功了。
继续来研究下它的注册算法, 通过上面爆破发现 核心在这5个比较跳转 只要让跳转能顺利走到 字符串 "注册了" 这个位置 哪就算成功了。这5个比较是一个循环检测并不需要点击注册按钮。
[Asm] 纯文本查看 复制代码 [mw_shl_code=asm,true]004473E7 | 81BB 04030000 340C0000 | cmp dword ptr ds:[ebx+304],C34 | exb+304 地址的值 和 0xC34 比较004473F1 | 0F84 88000000 | je ckme002.44747F |
004473F7 | 81BB 08030000 0D230000 | cmp dword ptr ds:[ebx+308],230D | ebx+308地址的值 和 0x230D比较
00447401 | 74 7C | je ckme002.44747F |
00447403 | 81BB 10030000 940F0000 | cmp dword ptr ds:[ebx+310],F94 | ebx+31 地址的值 和 0xF94 比较
0044740D | 75 70 | jne ckme002.44747F |
0044740F | 8B83 18030000 | mov eax,dword ptr ds:[ebx+318] |
00447415 | 3B83 14030000 | cmp eax,dword ptr ds:[ebx+314] | 相当于 ebx+318 和 ebx+314 地址的值比较
0044741B | 75 62 | jne ckme002.44747F |
0044741D | 81BB 1C030000 E7030000 | cmp dword ptr ds:[ebx+31C],3E7 |
00447427 | 74 56 | je ckme002.44747F | [/mw_shl_code]
现在就要主要看这5个重要的比较
比较1: cmp dword ptr ds:[ebx+304],C34 exb+0x304 和 0xC34进行比较 如果相等 就跳转 否则就不跳转。 这个比较肯定要让它不等于0xC34 才能走到下一个跳转里面。那目前的重点就是 怎么找到 exb+0x304地址的值是在哪里有赋值操作的,看他比较的时候固定和0xC34做比较 先搜索一下常量0xC34看一下。
1
搜索完 我们发现了 一共有3个位置使用了0xC34这个常量值, 赋值操作只有第一个和第二个 所以只看这两个。
这两个赋值0xC34的地方 有两个跳转 第一个跳转要让他不进行跳转 第二个跳转要让他进行跳转 才可以避免赋值 0x3C ,在跳转这个地方下一个断点,不知道这个断点是怎么触发的,推测是启动的时候就判断个什么东西然后给赋了一个初始值(因为我之前下了硬件访问断点发现后面别没有什么操作能让他断下来 才有的这个推测)
果然 重启之后直接断了下来 我们看一下 这部分的代码 来分析一下: 首先会判断 X:\\ajj.126.c0m\\j\\o\\j\\o\\ok.txt 这个路径是否存在 如果不存在直接直接跳转赋值0xC34。
2
因为我电脑并没有X盘 所以我把他改成了C盘 这样第一个跳转就不会成立了。
再来看一下第二个跳转,有3个CALL 大概执行的功能就是 把文本里面的值读出来跟固定读取出来的内容和0x446E14内存地址里面的字符做对比。需要让他一致才能这个跳转才能跳过。
3
因为0x446E14地址里面的字符串是乱码(不知道是什么编码) 所以我们直接用Win Hex把这个16进制数据储存进去:
00446E14 6A6A6120 ajj
00446E18 C4B5B4D0 дµÄ
00446E1C 656D4B43 CKme
00446E20 C3C0E6D5 ÕæÀÃ
00446E24 00FFFF21 !ÿÿ.
内存是小端序存储 并且字符串是以0结尾 所以 我们的格式应该是 : 20 61 6A 6A D0 B4 B5 C4 43 4B 6D 65 D5 E6 C0 C3 21 FF FF
储存完成之后 在运行程序 这个跳转已经能跳过了, 至此 我们的 5个比较 其中的第1个已经搞定了。
第1个比较搞定后发现 程序界面多出来了一个文本框 但是不能输入任何内容。 先不管他 继续看第二个比较。
比较2:cmp dword ptr ds:[ebx+308],230D ebx+308地址的值 和 0x230D 进行比较 ,也是一样 要让 ebx+308地址里面的值不等于0x230D才可以,还是搜索常量看一下。搜索后发现在这个位置有赋值0x230D的操作。 但是这块代码是怎么触发的呢? 目前程序上 只有一个 可用的文本框 和一个不可用的文本框和一个注册按钮。
首先重启一下程序看一下会不会断下来,重启后发现程序并不会断下来,继续在可输入文本框里面输入内容 发现也不会断下来,那现在能操作的就只有这个注册按钮了,如果点击注册按钮也段不来了,那就只能用e2a看一下这个程序都有哪些事件然后逐一查看了。
好在点击注册断了下来, 既然断下来了我们就来逐行分析一下代码。
[Asm] 纯文本查看 复制代码 [mw_shl_code=asm,true]00446FA4 | 55 | push ebp |
00446FA5 | 8BEC | mov ebp,esp |
00446FA7 | 8B90 08030000 | mov edx,dword ptr ds:[eax+308] | eax+308 就是 第2个比较的ebx+308的位置
00446FAD | 81FA 0D230000 | cmp edx,230D | 取出 第2个比较值 和 0x23D作比较 初始值为 0x28E
00446FB3 | 74 20 | je ckme002111.446FD5 | 如果成立 相当于就不会赋值 0x230D
00446FB5 | 80F9 01 | cmp cl,1 |
00446FB8 | 75 09 | jne ckme002111.446FC3 | 如果cl等于0x1 就会给 第2个比较的值增加0x3 并且jmp跳过赋值0x230D
00446FBA | 8380 08030000 03 | add dword ptr ds:[eax+308],3 |
00446FC1 | EB 12 | jmp ckme002111.446FD5 |
00446FC3 | 81FA 94020000 | cmp edx,294 |
00446FC9 | 7D 0A | jge ckme002111.446FD5 | 如果第2个比较的值大于等于0x294 就不会赋值0x23D
00446FCB | C780 08030000 0D230000 | mov dword ptr ds:[eax+308],230D |
00446FD5 | 5D | pop ebp |
00446FD6 | C2 0C00 | ret C | [/mw_shl_code]
通过上面代码 有几个疑问:
1:如果我不点击注册按钮 那它的初始值就默认是 0x28E了 跟 0x23D 直接就不一样了 我不点击注册不就直接可以了吗?
2:如果我点击了注册那还有一个比较 那就是 cl寄存器 和0x1 比较 只有相等才不会赋值 0x23D并且还会把第二个比较值加0x3。如果点击注册必须让cl寄存器的值等于0x1才行 那 cl寄存器代表的到底是什么 ?
如果我不点击注册 第二个比较确实直接就搞定了,可是我不点击注册 我应该操作什么 ?思路直接就卡死了。。。我要是点击注册 那必须要让 cl寄存器的值为0x1。
后面代码cl寄存器不等于0x1 会再次比较第二个初始值是否大于等于0x294 如果大于等于 它也不会赋值0x23D。 因为初始值是0x28E 如果想让他达到0x294 就要加2次0x3,直接点说就是:点击注册的前两次 只要cl寄存器的值为0x1 后面在点击 注册 无论它是不是0x1都不会赋值0x23D了。
分析到现在卡死了 我决定重新用e2a分析一下这个程序到底都有哪些事件。 针对事件在一点点进行梳理。通过e2a查看组件的事件 我们发现 有好多隐藏的动作是我们不知道的,比如 图片框有双击事件 每个图片也有对应的鼠标按下事件等等... 。
6
现在主要看这个注册按钮的事件,注册按钮有两个事件 一个是左键单击 一个是鼠标按下。
首先跳转到0x004474C0 看鼠标单击事件, 它只有这一行代码 把eax+0x31c地址赋值为0x3E7
然后跳转到0x00446FA4 看鼠标按下事件, 鼠标单击的同时还会触发鼠标按下的事件,之前鼠标左键单击注册按钮 cl寄存器的值就为0,既然注册按钮除了单击事件外还有鼠标按下事件 咱们还可以按下鼠标右键 按下滑轮键 都可以触发这个事件 咱们逐一来试一下。经过测试发现 按下滑轮键 cl寄存器的值为0x2, 按下鼠标右键 cl的值为0x1。
7
如果启动程序不左键单击注册按钮 或者 右键单击注册按钮 第二个比较都不会跳转,但是右键单击会把ebx+0x308的值增加0x3 具体作用是什么现在还不得而知。反正比较2已经不会进行赋值0x23D了 那就先分析到这里。
(意外收获)用e2a查看了事件后我每个事件地址都进去备注了一下,在查看到双击图片框的事件的时候发现了刚刚 比较2里面右键单击会把ebx+0x308的值增加0x3 如果ebx+0x308的值增加到 0x29D的时候去双击图片框(注意是图片框 不是图片)就会调用一个CALL,但是有什么用不知道 咱们先来测试一下。 之前说过 ebx+0x308的初始值是 0x28E ,右键点击一次注册增加0x3,那就右键点击5次之后在双击这个图片框就会调用这个CALL,先来测试一下它到底是干什么的。执行完成之后我们发现原本禁用的输入框现在解除禁用了。
8
比较3:cmp dword ptr ds:[ebx+310],F94 要让ebx+0x310的值等于0xF94,首先还是搜索常量0xF94看一下能不能定位到赋值的地方。
定位到了地址0x0044715A 是比较3的关键赋值。这块代码是窗口上移动鼠标的事件代码,在窗口上移动鼠标就会执行这部分代码,但是想走到0x0044715A 这个赋值代码 上面还有好多个比较跳转。按照正向思维来分析 既然这个地方是捕捉窗口鼠标移动的事件 那我肯定要拿到鼠标的x,y坐标才能在去干其它的事情 否则进行捕捉鼠标动作也没什么意义,所以这些判断可能都跟鼠标的坐标值有关系。
程序窗口尺寸为260,316我是鼠标从右下移动到程序界面然后断点断下 看到EAX的值是0x101 EDX是0X13B, 对应十进制就是 257,315。
9
继续往下看,这部分代码是干什么用的不太清楚。
[Asm] 纯文本查看 复制代码 004470FE | 55 | push ebp |
004470FF | 68 17724400 | push ckme002111.447217 |
00447104 | 64:FF31 | push dword ptr fs:[ecx] |
00447107 | 64:8921 | mov dword ptr fs:[ecx],esp |
0044710A | 8B8B E0020000 | mov ecx,dword ptr ds:[ebx+2E0] | ecx:&"宂B", [ebx+2E0]:&"宂B"
00447110 | 8079 47 01 | cmp byte ptr ds:[ecx+47],1 | 取 ecx+47 的一个字节 比较值是否为0x1
00447114 | 75 19 | jne ckme002111.44712F |
00447116 | 3D E2000000 | cmp eax,E2 | 比较X坐标是否大于等于e2
0044711B | 7E 12 | jle ckme002111.44712F |
0044711D | 81FA 2C010000 | cmp edx,12C | 比较Y坐标是否大于等于12C
00447123 | 7E 0A | jle ckme002111.44712F |
00447125 | C783 10030000 10000000 | mov dword ptr ds:[ebx+310],10 | 比较都满足的 给ebx赋值310
翻译成正向代码就是:
If(ecx+0x47 == 0x1 and x坐标 >= 0xE2 and y坐标 >= 0x12C)
{
EBX+0x310 = 0x10;
}
继续看下面的代码 有一个跳转,是ecx+47地址的值拿出一个字节和0x1比较,我们要进入到这个跳转里面才可以。继续搜索常量 0x47看一下能不能定位到。
10
通过搜索定位到了关键处,发现了这个ecx+47位置的值是实时变动的 只要图片改变对应的值也会改变。
当图片框图片到达第三个的时候 这个地址里面的值自动就变成了0x01010101,只取一个字节,那这个值就是0x1。这样也就是说,等到是第三张图片的时候 我们把鼠标移动到程序内 这个跳转就不会进行跳了,现在来试一下。
13
测试完后发现第一个跳转不跳了 第二个跳转还是跳那也就是说明 这两个ecx+0x47不是一个地址。我们仔细看一下这两个跳转的上2行代码 确实不是一个地址,之前没注意,第一个跳转的ecx地址是ebx+0x20 第二个是 ebx+0x2DC。
之前找的播放到图片3的时候 对应的是第一个跳转赋值0x1的代码,现在我们单步到第二个跳转的位置 在内存窗口重新跟随到 ecx+0x47内存地址 然后放开程序 在观察一下 第二个跳转是什么时候赋值0x1的。
通过上面的分析发现,第一个跳转是在第三张图的时候不成立 第二个跳转是在第2张图的时候不成立,那我们等到他运行到第二张图的时候 在把鼠标放到程序内看一下。
14
这个时候跳转就不成立可以正常往下走了,然后下面还有一些跳转代码 我们要让他全部不进行跳转才可以走到 比较3的关键赋值位置。
通过下面这部分代码可以看出:第一个跳转:鼠标X坐标要小于0x17对应十进制就是23才能不跳转第二个跳转:鼠标Y坐标要大于0x12C对应十进制300才能不跳转。 说人话就是第一个第二个跳转鼠标要从左下角移动到程序内才不跳。
[Asm] 纯文本查看 复制代码 0044713B | 83F8 17 | cmp eax,17 |
0044713E | 7D 67 | jge ckme002111.4471A7 | 大于等于X坐标跳转
00447140 | 81FA 2C010000 | cmp edx,12C |
00447146 | 7E 5F | jle ckme002111.4471A7 | 小于等于Y坐标跳转
00447148 | 83BB 10030000 10 | cmp dword ptr ds:[ebx+310],10 |
0044714F | 75 56 | jne ckme002111.4471A7 | ebx+310 不等于 0x10 跳转
00447151 | 83BB 0C030000 09 | cmp dword ptr ds:[ebx+30C],9 | ebx+30C等于0x9 跳转
00447158 | 74 4D | je ckme002111.4471A7 |
已经分析完了前两个跳转怎么让他不跳,我们先来试一下(在第二张图的时候鼠标从左下角移动到程序内)
现在已经顺利的走到第三个跳转了,第三个跳转 ebx+0x310 等于0x10就不会跳,那对应下图的就是这部分代码满足就会给ebx+0x310赋值0x10。相当于 在第三张图片的时候 鼠标从右下角移动到程序内(自己转换一下坐标值就知道了) 然后在等到第二张图的时候鼠标从左下移动到程序内 这三个跳转就都不会跳了。
还差最后一个跳转比较3就搞定了, 现在来看一下怎么才能让ebx+0x30C的位置不等于0x9,继续搜索常数0x30C。搜索后在文本框2双击事件里面找到了这个 ebx+0x30C的赋值(每一个事件之前都用e2a都看过了一遍并备注了 所以才知道是在哪个事件里面)。
来分析下面代码,看它是什么逻辑才能成功走到给ebx+30C赋值的位置。
[Asm] 纯文本查看 复制代码 00446FF8 | 55 | push ebp | 文本框2双击事件
00446FF9 | 8BEC | mov ebp,esp |
00446FFB | 33C9 | xor ecx,ecx | ecx:&"宂B"
00446FFD | 51 | push ecx | ecx:&"宂B"
00446FFE | 51 | push ecx | ecx:&"宂B"
00446FFF | 51 | push ecx | ecx:&"宂B"
00447000 | 51 | push ecx | ecx:&"宂B"
00447001 | 51 | push ecx | ecx:&"宂B"
00447002 | 53 | push ebx | ebx:&"<珺"
00447003 | 8BD8 | mov ebx,eax | ebx:&"<珺"
00447005 | 33C0 | xor eax,eax |
00447007 | 55 | push ebp |
00447008 | 68 DF704400 | push ckme002111.4470DF |
0044700D | 64:FF30 | push dword ptr fs:[eax] |
00447010 | 64:8920 | mov dword ptr fs:[eax],esp |
00447013 | 8D55 FC | lea edx,dword ptr ss:[ebp-4] |
00447016 | 8B83 F0020000 | mov eax,dword ptr ds:[ebx+2F0] | [ebx+2F0]:&"<珺"
0044701C | E8 6BD0FDFF | call ckme002111.42408C | 取出文本框2内容
00447021 | 8B45 FC | mov eax,dword ptr ss:[ebp-4] |
00447024 | E8 5FCBFBFF | call ckme002111.403B88 | 获取文本长度
00447029 | 83F8 08 | cmp eax,8 | 长度和0x8比较 也就是要求文本框2必须输入8位
0044702C | 0F85 92000000 | jne ckme002111.4470C4 |
00447032 | 8D55 F8 | lea edx,dword ptr ss:[ebp-8] |
00447035 | 8B83 F0020000 | mov eax,dword ptr ds:[ebx+2F0] | [ebx+2F0]:&"<珺"
0044703B | E8 4CD0FDFF | call ckme002111.42408C |
00447040 | 8B45 F8 | mov eax,dword ptr ss:[ebp-8] |
00447043 | 8078 01 5F | cmp byte ptr ds:[eax+1],5F | 5F='_' 文本框2内容第二个字节和 '_' 比较
00447047 | 75 7B | jne ckme002111.4470C4 |
00447049 | 8D55 F4 | lea edx,dword ptr ss:[ebp-C] | [ebp-C]:&"<珺"
0044704C | 8B83 F0020000 | mov eax,dword ptr ds:[ebx+2F0] | [ebx+2F0]:&"<珺"
00447052 | E8 35D0FDFF | call ckme002111.42408C |
00447057 | 8B45 F4 | mov eax,dword ptr ss:[ebp-C] | [ebp-C]:&"<珺"
0044705A | 8078 05 2C | cmp byte ptr ds:[eax+5],2C | 2C=',' 文本框2第5个字节和 ',' 比较
0044705E | 75 64 | jne ckme002111.4470C4 |
00447060 | 8D55 F0 | lea edx,dword ptr ss:[ebp-10] |
00447063 | 8B83 E8020000 | mov eax,dword ptr ds:[ebx+2E8] | [ebx+2E8]:&"<珺"
00447069 | E8 1ED0FDFF | call ckme002111.42408C | 取出文本框1内存
0044706E | 8B45 F0 | mov eax,dword ptr ss:[ebp-10] |
00447071 | E8 12CBFBFF | call ckme002111.403B88 | 取出文本框1长度
00447076 | 83C0 03 | add eax,3 | 文本框1内存长度+0x3
00447079 | B9 03000000 | mov ecx,3 | ecx:&"宂B"
0044707E | 99 | cdq |
0044707F | F7F9 | idiv ecx | eax/ecx 商存eax 余数存edx
00447081 | 85D2 | test edx,edx | 判断 eax+3 后能否被3整除
00447083 | 75 3F | jne ckme002111.4470C4 |
00447085 | 6A 00 | push 0 |
00447087 | 6A 04 | push 4 |
00447089 | 8D55 EC | lea edx,dword ptr ss:[ebp-14] |
0044708C | 8B83 E8020000 | mov eax,dword ptr ds:[ebx+2E8] | [ebx+2E8]:&"<珺"
00447092 | E8 F5CFFDFF | call ckme002111.42408C |
00447097 | 8B45 EC | mov eax,dword ptr ss:[ebp-14] |
0044709A | E8 E9CAFBFF | call ckme002111.403B88 |
0044709F | 99 | cdq |
004470A0 | 52 | push edx |
004470A1 | 50 | push eax |
004470A2 | 33C0 | xor eax,eax |
004470A4 | E8 E70EFCFF | call ckme002111.407F90 |
004470A9 | 030424 | add eax,dword ptr ss:[esp] |
004470AC | 135424 04 | adc edx,dword ptr ss:[esp+4] |
004470B0 | 83C4 08 | add esp,8 |
004470B3 | 83C0 02 | add eax,2 |
004470B6 | 83D2 00 | adc edx,0 |
004470B9 | E8 47ECFBFF | call ckme002111.405D05 |
004470BE | 8983 0C030000 | mov dword ptr ds:[ebx+30C],eax | ebx+30C 赋值位置
004470C4 | 33C0 | xor eax,eax |
004470C6 | 5A | pop edx |
004470C7 | 59 | pop ecx | ecx:&"宂B"
004470C8 | 59 | pop ecx | ecx:&"宂B"
004470C9 | 64:8910 | mov dword ptr fs:[eax],edx |
004470CC | 68 E6704400 | push ckme002111.4470E6 | 4470E6:"[嬪]脨虌靔"
004470D1 | 8D45 EC | lea eax,dword ptr ss:[ebp-14] |
004470D4 | BA 05000000 | mov edx,5 |
004470D9 | E8 4EC8FBFF | call ckme002111.40392C |
004470DE | C3 | ret |
首先取出了输入框2的内容 接着判断内容长度是否等于0x8,在判断了第一个字节是否等于字符 “_”,在判断 第五个字节是否等于字符 “,” 。然后又取文本框1内容长度+0x3和3进行取模运算是否等于0。
正向代码:[C++] 纯文本查看 复制代码 int main() { //对应文本框1
string user = "a12345";
//对应文本框2
string password = "a_asa,as";
if (password.length() == 0x8 and password[1] == 0x5F and password[5] == 0x2C)
{
int len = user.length() + 0x3;
if (len % 3 == 0)
{
//ebx+0x30=eax;
}
}
return 0;
}
比较4:mov eax,dword ptr ds:[ebx+318] cmp eax,dword ptr ds:[ebx+314] 相当于要让 ebx+0x318 和 ebx+0x314的值相等才可以。首先看ebx+0x314赋值的地方 这个地方之前已经看到了,其实就在分析比较3的时候 把ebx+0x310赋值完0xF94之后之后执行的代码
通过这段代码就可以很清楚的看出 给ebx+0x314赋值什么 取决于刚才在分析比较ebx+0x30C赋的值是什么。具体是怎么计算的先不管它反正就只有这4个固定的值。
继续往下看还有一个跳转执行完这个跳转才会出CALL,看一下这个跳转里面干了什么。
首先取了文本1内容 也就是用户名 然后和字符串 “ajj”对比 如果相等还会执行3个CALL 。那就把用户名改成ajj试一下会发生什么。
如果用户名输入ajj 就会把ebx+0x30C的值显示到程序上面,通过这个显示的值我们就知道 ebx+0x314赋值什么。也就是说 用户名只能输入ajj 这个才是正确的用户名 输入完后看程序上显示的是什么,如果是0那ebx+0x314赋值0x41,1赋值0x3D,2赋值0x34 ,3赋值0xDF。现在已经搞清楚了ebx+0x314的赋值方式,怎么才能让ebx+0x318的值等于ebx+0x314的值? 这个时候要继续去看ebx+0x318是在哪里赋值了。
还是搜索常量0x318,搜索完我们发现 只有第一个是直接赋值了一个eax 剩下的都是在它本身的值做自增操作,先进到第一个赋值操作看一下。
第一个进去后发现 这个是启动的时候直接就赋初始值0x0。继续往下看第二个
第二个进去后发现是图片1的鼠标按下事件,会根据bl寄存器判断是左键点击的还是右键点击的,如果是左键那就加0x2 右键加0x11。
剩下的3个图片按下事件同理只不过加的值不一样,通过上面的常量搜索出来的值大家可以自行进入看一下我就不一一列出了,我直接把对应的值发出来了:
图片1鼠标左键增加:0x2 右键增加:0x11
图片2鼠标左键增加:0x3 右键增加:0x13
图片3鼠标左键增加:0x5 右键增加:0x17
图片4鼠标左键增加:0x7 右键增加:0x1B
自己计算出来对应的图片左键点还是右键点 把值加到和 ebx+0x314的值一样即可。
比较5:cmp dword ptr ds:[ebx+31C],3E7 让ebx+317的值不等于0x3E7即可, 这个咱们在程序最开始的爆破的时候就看到了,左键单击按钮注册事件,注册按钮不能左键点 只要不点就不会赋值0x3E7
把上面所有的分析出来的流程全部操作一遍就注册成功了
至此 程序的全部逆向分析过程就算完成了。
总结:
1.首先创建一个"X:\\ajj.126.c0m\\j\\o\\j\\o\\ok.txt"的文本里面储存十六进制数据 20 61 6A 6A D0 B4 B5 C4 43 4B 6D 65 D5 E6 C0 C3 21 FF FF。
2.用户名输入ajj 密码按照这种格式输入: x_xxx,xx
3.鼠标在第三张图的时候 从右下角移动到程序内 然后在第二张图的时候在左下角移动到程序内
4.按照上述操作完成后 程序上会出现一个 0 1 2 3 的数字,分别对应数值 0x41,0x3D,0x34 ,0xDF
5.每一个图片左键或者右键单击都会对应增加数值 具体增加数值看上面内容,自己点击到数值和上面的 0 1 2 3对应的数值相等。
6.不能左键点注册按钮
完成以上的操作 就算是注册成功了。 注册机就不写了。这个程序比较另类 这种验证方式我估计用户是接受不了,我也接受不了!!! 亲爱的ajj作者你有想过你的程序经历24年还会给一个初学者带来暴击吗?? |
-
5
-
4
免费评分
-
查看全部评分
|