-
-
[旧帖] [原创][文章标题]: BitRecorder1.61算法分析 0.00雪花
-
发表于: 2009-6-30 16:03 3506
-
【文章标题】: BitRecorder1.61算法分析
【文章作者】: 萧萧黄叶
【作者邮箱】:
【作者主页】:
【作者QQ号】:
【软件名称】: BitRecorder1.61
【下载地址】: 自己搜索下载
【加壳方式】: ASPack 2.12 -> Alexey Solodovnikov
【保护方式】:
【编写语言】:
【使用工具】:
【操作平台】:
【软件介绍】:
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
-----------------------------------------------------------------
---------------
【详细过程】
先试运行程序,跳出对话框提示要注册,用假码注册看看有什么提示:“
Sorry, the Code is error.”
PEiD探壳:ASPack 2.12 -> Alexey Solodovnikov
一个很简单的压缩壳,用ESP定律找到OEP为22FAE进行脱壳,再用PEiD探
壳:Microsoft Visual C++ 6.0
并且程序能够正常运行。
C32Asm反汇编找到:
00421C58 PUSH 42CCC0 \->:
Sorry, the Code is error.
00421BFE PUSH 42CCE8 \->: Thank
you for registering BitRecorder
OK,用OD载入脱壳后的文件,程序停在这里:
00422FAE >/$ 55 push ebp
00422FAF |. 8BEC mov ebp,esp
00422FB1 |. 6A FF push -1
根据反汇编的提示在OD中下断点,运行程序,用假码注册,断在这里:
00421B30 . 6A FF push -1
00421B32 . 68 B0534200 push 22FAE.004253B0
; SE 处理程序安装
继续F8单步:
00421B37 . 64:A1 0000000>mov eax,dword ptr fs:[0]
00421B3D . 50 push eax
00421B3E . 64:8925 00000>mov dword ptr fs:[0],esp
00421B45 . 83EC 10 sub esp,10
00421B48 . 53 push ebx
00421B49 . 56 push esi
00421B4A . 57 push edi
00421B4B . 8BF1 mov esi,ecx
00421B4D . 6A 01 push 1
00421B4F . E8 E4100000 call <jmp.&mfc42.#6334>
00421B54 . 51 push ecx
; 经过上面这个CALL,用户名的后面一部分出现在寄存器EDX中
00421B55 . 8D7E 60 lea edi,dword ptr ds:[esi+60]
00421B58 . 8BCC mov ecx,esp
00421B5A . 896424 10 mov dword ptr ss:[esp+10],esp
00421B5E . 57 push edi
00421B5F . E8 B40C0000 call <jmp.&mfc42.#535>
00421B64 . 51 push ecx
; 经过上面这个CALL,注册码出现在堆栈中
00421B65 . 8D5E 64 lea ebx,dword ptr ds:[esi+64]
00421B68 . 8BCC mov ecx,esp
00421B6A . 896424 18 mov dword ptr ss:[esp+18],esp
00421B6E . 53 push ebx
00421B6F . C74424 30 000>mov dword ptr ss:[esp+30],0
00421B77 . E8 9C0C0000 call <jmp.&mfc42.#535>
00421B7C . C74424 2C FFF>mov dword ptr ss:[esp+2C],-1
; 经过上面这个CALL,用户名出现在堆栈中
00421B84 . E8 F7A5FEFF call 22FAE.0040C180
; 眼看着下面的跳转就要决定注册的成败,所以这里应该就是关键
CALL了,必须跟进!
00421B89 . 83C4 08 add esp,8
00421B8C . 85C0 test eax,eax
; 经过上面的CALL运算后如果EAX=0,下面的跳转就会实现,注册就
失败了。所以在关键CALL中要注意EAX的值。
0040C180 /$ 6A FF push -1
0040C182 |. 68 A83E4200 push 22FAE.00423EA8
; SE 处理程序安装
0040C187 |. 64:A1 0000000>mov eax,dword ptr fs:
[0]
0040C18D |. 50 push eax
0040C18E |. 64:8925 00000>mov dword ptr fs:
[0],esp
0040C195 |. 83EC 10 sub esp,10
0040C198 |. 53 push ebx
0040C199 |. 8D4C24 04 lea ecx,dword ptr ss:
[esp+4]
0040C19D |. C74424 1C 010>mov dword ptr ss:
[esp+1C],1
0040C1A5 |. E8 20660100 call <jmp.&mfc42.#540>
0040C1AA |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C1AE |. C64424 1C 02 mov byte ptr ss:
[esp+1C],2
0040C1B3 |. E8 12660100 call <jmp.&mfc42.#540>
0040C1B8 |. 8D4C24 08 lea ecx,dword ptr ss:
[esp+8]
0040C1BC |. C64424 1C 03 mov byte ptr ss:
[esp+1C],3
0040C1C1 |. E8 04660100 call <jmp.&mfc42.#540>
0040C1C6 |. 8B4424 28 mov eax,dword ptr ss:
[esp+28] ; 将注册码移动到EAX
0040C1CA |. B3 04 mov bl,4
0040C1CC |. 885C24 1C mov byte ptr ss:
[esp+1C],bl
0040C1D0 |. 8B40 F8 mov eax,dword ptr ds:
[eax-8] ; 取注册码的位数到EAX
0040C1D3 |. 85C0 test eax,eax
0040C1D5 |. 0F8E 78010000 jle 22FAE.0040C353
; 如果EAX为0,跳转实现,跳越计算,直接就毙了
0040C1DB |. 56 push esi
0040C1DC |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C1E0 |. 6A 01 push 1
0040C1E2 |. 51 push ecx
0040C1E3 |. 8D4C24 34 lea ecx,dword ptr ss:
[esp+34]
0040C1E7 |. E8 38660100 call
<jmp.&mfc42.#4129>
0040C1EC |. 8B00 mov eax,dword ptr ds:
[eax]
0040C1EE |. 50 push eax
; /s
0040C1EF |. FF15 48664200 call dword ptr ds:
[<&msvcrt.atoi>] ; \atoi
0040C1F5 |. 83C4 04 add esp,4
0040C1F8 |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C1FC |. 8BF0 mov esi,eax
0040C1FE |. E8 B5650100 call <jmp.&mfc42.#800>
0040C203 |. 8B5424 2C mov edx,dword ptr ss:
[esp+2C]
0040C207 |. 8D4C24 2C lea ecx,dword ptr ss:
[esp+2C]
0040C20B |. 8B42 F8 mov eax,dword ptr ds:
[edx-8]
0040C20E |. 48 dec eax
0040C20F |. 50 push eax
0040C210 |. 8D4424 18 lea eax,dword ptr ss:
[esp+18]
0040C214 |. 50 push eax
0040C215 |. E8 10660100 call
<jmp.&mfc42.#5710>
0040C21A |. 50 push eax
0040C21B |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C21F |. C64424 24 05 mov byte ptr ss:
[esp+24],5
0040C224 |. E8 DD650100 call <jmp.&mfc42.#858>
0040C229 |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C22D |. 885C24 20 mov byte ptr ss:
[esp+20],bl
0040C231 |. E8 82650100 call <jmp.&mfc42.#800>
0040C236 |. 8B4C24 2C mov ecx,dword ptr ss:
[esp+2C]
0040C23A |. 8D5424 14 lea edx,dword ptr ss:
[esp+14]
0040C23E |. 8B41 F8 mov eax,dword ptr ds:
[ecx-8]
0040C241 |. 8D4C24 2C lea ecx,dword ptr ss:
[esp+2C]
0040C245 |. 2BC6 sub eax,esi
0040C247 |. 48 dec eax
0040C248 |. 50 push eax
0040C249 |. 52 push edx
0040C24A |. E8 DB650100 call
<jmp.&mfc42.#5710>
0040C24F |. 50 push eax
0040C250 |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C254 |. C64424 24 06 mov byte ptr ss:
[esp+24],6
0040C259 |. E8 A8650100 call <jmp.&mfc42.#858>
0040C25E |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C262 |. 885C24 20 mov byte ptr ss:
[esp+20],bl
0040C266 |. E8 4D650100 call <jmp.&mfc42.#800>
0040C26B |. 8D4424 14 lea eax,dword ptr ss:
[esp+14]
0040C26F |. 56 push esi
0040C270 |. 50 push eax
0040C271 |. 8D4C24 10 lea ecx,dword ptr ss:
[esp+10]
0040C275 |. E8 AA650100 call
<jmp.&mfc42.#4129>
0040C27A |. 50 push eax
0040C27B |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C27F |. C64424 24 07 mov byte ptr ss:
[esp+24],7
0040C284 |. E8 7D650100 call <jmp.&mfc42.#858>
0040C289 |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C28D |. 885C24 20 mov byte ptr ss:
[esp+20],bl
0040C291 |. E8 22650100 call <jmp.&mfc42.#800>
0040C296 |. 8D4C24 08 lea ecx,dword ptr ss:
[esp+8]
0040C29A |. 68 8CC24200 push 22FAE.0042C28C
; ASCII "Bit-Recorder-12"这是一个固定字符
0040C29F |. 8D5424 18 lea edx,dword ptr ss:
[esp+18]
0040C2A3 |. 51 push ecx
0040C2A4 |. 52 push edx
0040C2A5 |. E8 CE680100 call <jmp.&mfc42.#924>
; 由注册码的第一位决定后面取相应数目的数字并连
到上面的固定字符的前面
0040C2AA |. 50 push eax
0040C2AB |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C2AF |. C64424 24 08 mov byte ptr ss:
[esp+24],8
0040C2B4 |. E8 4D650100 call <jmp.&mfc42.#858>
0040C2B9 |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C2BD |. 885C24 20 mov byte ptr ss:
[esp+20],bl
0040C2C1 |. E8 F2640100 call <jmp.&mfc42.#800>
0040C2C6 |. 8B4424 08 mov eax,dword ptr ss:
[esp+8]
0040C2CA |. 50 push eax
0040C2CB |. E8 D0300100 call 22FAE.0041F3A0
; 这个CALL是对刚才加工后的字符串进行了MD5加密。
0040C2D0 |. 83C4 04 add esp,4
0040C2D3 |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C2D7 |. 50 push eax
0040C2D8 |. E8 35650100 call <jmp.&mfc42.#860>
0040C2DD |. 8B4C24 0C mov ecx,dword ptr ss:
[esp+C]
0040C2E1 |. 8B5424 10 mov edx,dword ptr ss:
[esp+10] ; 下面的S1等于注册码除去前两位后面的剩余部分
,S1等于MD5加密值。再下面的CALL从字面上理解就是CMP,比较了。
0040C2E5 |. 51 push ecx
; /s2
0040C2E6 |. 52 push edx
; |s1
0040C2E7 |. FF15 3C664200 call dword ptr ds:
[<&msvcrt._mbscmp>] ; \_mbscmp
77C01881 > 8BFF mov
edi,edi
77C01883 55 push ebp
77C01884 8BEC mov
ebp,esp
77C01886 56 push esi
77C01887 E8 99860000 call
msvcrt.77C09F25
77C0188C 8B70 60 mov
esi,dword ptr ds:[eax+60]
77C0188F 3B35 4425C377 cmp
esi,dword ptr ds:[77C32544]
77C01895 74 07 je short
msvcrt.77C0189E
77C01897 E8 91EDFFFF call
msvcrt.77C0062D
77C0189C 8BF0 mov
esi,eax
77C0189E 837E 08 00 cmp
dword ptr ds:[esi+8],0
77C018A2 75 2F jnz
short msvcrt.77C018D3
77C018A4 8B75 0C mov
esi,dword ptr ss:[ebp+C]
77C018A7 8B45 08 mov
eax,dword ptr ss:[ebp+8]
77C018AA 8A10 mov
dl,byte ptr ds:[eax]
77C018AC 8ACA mov
cl,dl
77C018AE 3A16 cmp
dl,byte ptr ds:[esi]
77C018B0 75 1A jnz
short msvcrt.77C018CC
77C018B2 84C9 test
cl,cl
77C018B4 74 12 je short
msvcrt.77C018C8
77C018B6 8A50 01 mov
dl,byte ptr ds:[eax+1]
77C018B9 8ACA mov
cl,dl
77C018BB 3A56 01 cmp
dl,byte ptr ds:[esi+1]
77C018BE 75 0C jnz
short msvcrt.77C018CC
77C018C0 40 inc eax
77C018C1 40 inc eax
77C018C2 46 inc esi
77C018C3 46 inc esi
77C018C4 84C9 test
cl,cl
77C018C6 ^ 75 E2 jnz
short msvcrt.77C018AA
77C018C8 33C0 xor
eax,eax
77C018CA EB 68 jmp
short msvcrt.77C01934
77C018CC 1BC0 sbb
eax,eax
77C018CE 83D8 FF sbb
eax,-1
77C018D1 EB 61 jmp
short msvcrt.77C01934
77C018D3 57 push edi
77C018D4 8B7D 0C mov
edi,dword ptr ss:[ebp+C]
77C018D7 53 push ebx
77C018D8 8B45 08 mov
eax,dword ptr ss:[ebp+8]
77C018DB 66:0FB600 movzx
ax,byte ptr ds:[eax] ; 取加工后的注册码的第一位的ASC
码到AX
77C018DF FF45 08 inc
dword ptr ss:[ebp+8]
77C018E2 0FB6C8 movzx
ecx,al
77C018E5 F64431 1D 04 test
byte ptr ds:[ecx+esi+1D],4
77C018EA 74 18 je short
msvcrt.77C01904
77C018EC 8B4D 08 mov
ecx,dword ptr ss:[ebp+8]
77C018EF 8A09 mov
cl,byte ptr ds:[ecx]
77C018F1 84C9 test
cl,cl
77C018F3 75 04 jnz
short msvcrt.77C018F9
77C018F5 33C0 xor
eax,eax
77C018F7 EB 0B jmp
short msvcrt.77C01904
77C018F9 33D2 xor
edx,edx
77C018FB FF45 08 inc
dword ptr ss:[ebp+8]
77C018FE 8AF0 mov
dh,al
77C01900 8AD1 mov
dl,cl
77C01902 8BC2 mov
eax,edx
77C01904 66:0FB60F movzx
cx,byte ptr ds:[edi] ; 取MD5加密值的第一位的ASC码到
CX
77C01908 0FB6D1 movzx
edx,cl
77C0190B 47 inc edi
77C0190C F64432 1D 04 test
byte ptr ds:[edx+esi+1D],4
77C01911 74 13 je short
msvcrt.77C01926
77C01913 8A17 mov
dl,byte ptr ds:[edi]
77C01915 84D2 test
dl,dl
77C01917 75 04 jnz
short msvcrt.77C0191D
77C01919 33C9 xor
ecx,ecx
77C0191B EB 09 jmp
short msvcrt.77C01926
77C0191D 33DB xor
ebx,ebx
77C0191F 8AF9 mov
bh,cl
77C01921 47 inc edi
77C01922 8ADA mov
bl,dl
77C01924 8BCB mov
ecx,ebx
77C01926 66:3BC8 cmp
cx,ax ; AX与CX进行比较,相等下面的
跳转就不跳,在返回之前会将EAX清零;否则跳转实现
77C01929 75 0C jnz
short msvcrt.77C01937
77C0192B 66:85C0 test
ax,ax
77C0192E ^ 75 A8 jnz
short msvcrt.77C018D8
77C01930 33C0 xor
eax,eax
77C01932 5B pop ebx
77C01933 5F pop edi
77C01934 5E pop esi
77C01935 5D pop ebp
77C01936 C3 retn
77C01937 1BC0 sbb
eax,eax ; 如果跳转到这里,会使EAX=1
77C01939 83E0 02 and
eax,2
77C0193C 48 dec eax
77C0193D ^ EB F3 jmp
short msvcrt.77C01932
0040C2ED |. 83C4 08 add esp,8
0040C2F0 |. C64424 20 03 mov byte ptr ss:
[esp+20],3
0040C2F5 |. 85C0 test eax,eax
0040C2F7 |. 5E pop esi
0040C2F8 |. 8D4C24 08 lea ecx,dword ptr ss:
[esp+8]
0040C2FC |. 75 5E jnz short
22FAE.0040C35C ; EAX的值将决定这里的跳转。一跳就
死!
0040C2FE |. E8 B5640100 call <jmp.&mfc42.#800>
0040C303 |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C307 |. C64424 1C 02 mov byte ptr ss:
[esp+1C],2
0040C30C |. E8 A7640100 call <jmp.&mfc42.#800>
0040C311 |. 8D4C24 04 lea ecx,dword ptr ss:
[esp+4]
0040C315 |. C64424 1C 01 mov byte ptr ss:
[esp+1C],1
0040C31A |. E8 99640100 call <jmp.&mfc42.#800>
0040C31F |. 8D4C24 24 lea ecx,dword ptr ss:
[esp+24]
0040C323 |. C64424 1C 00 mov byte ptr ss:
[esp+1C],0
0040C328 |. E8 8B640100 call <jmp.&mfc42.#800>
0040C32D |. 8D4C24 28 lea ecx,dword ptr ss:
[esp+28]
0040C331 |. C74424 1C FFF>mov dword ptr ss:
[esp+1C],-1
0040C339 |. E8 7A640100 call <jmp.&mfc42.#800>
0040C33E |. B8 01000000 mov eax,1
; 这里会给EAX赋值为1
0040C343 |. 5B pop ebx
0040C344 |. 8B4C24 10 mov ecx,dword ptr ss:
[esp+10]
0040C348 |. 64:890D 00000>mov dword ptr fs:
[0],ecx
0040C34F |. 83C4 1C add esp,1C
0040C352 |. C3 retn
0040C353 |> C64424 1C 03 mov byte ptr ss:
[esp+1C],3
0040C358 |. 8D4C24 08 lea ecx,dword ptr ss:
[esp+8]
0040C35C |> E8 57640100 call <jmp.&mfc42.#800>
0040C361 |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C365 |. C64424 1C 02 mov byte ptr ss:
[esp+1C],2
0040C36A |. E8 49640100 call <jmp.&mfc42.#800>
0040C36F |. 8D4C24 04 lea ecx,dword ptr ss:
[esp+4]
0040C373 |. C64424 1C 01 mov byte ptr ss:
[esp+1C],1
0040C378 |. E8 3B640100 call <jmp.&mfc42.#800>
0040C37D |. 8D4C24 24 lea ecx,dword ptr ss:
[esp+24]
0040C381 |. C64424 1C 00 mov byte ptr ss:
[esp+1C],0
0040C386 |. E8 2D640100 call <jmp.&mfc42.#800>
0040C38B |. 8D4C24 28 lea ecx,dword ptr ss:
[esp+28]
0040C38F |. C74424 1C FFF>mov dword ptr ss:
[esp+1C],-1
0040C397 |. E8 1C640100 call <jmp.&mfc42.#800>
0040C39C |. 8B4C24 14 mov ecx,dword ptr ss:
[esp+14]
0040C3A0 |. 33C0 xor eax,eax
; 这里是将EAX清零
0040C3A2 |. 5B pop ebx
0040C3A3 |. 64:890D 00000>mov dword ptr fs:
[0],ecx
0040C3AA |. 83C4 1C add esp,1C
0040C3AD \. C3 retn
00421B8E . 0F84 C0000000 je 22FAE.00421C54
; 关键跳,一跳就死!
00421B94 . 68 01000080 push 80000001
00421B99 . 8D4C24 18 lea ecx,dword ptr ss:[esp+18]
00421B9D . E8 1E020000 call 22FAE.00421DC0
00421BA2 . 68 64C44200 push 22FAE.0042C464
; ASCII "SOFTWARE\BitRecorder"
00421BA7 . 8D4C24 18 lea ecx,dword ptr ss:[esp+18]
00421BAB . C74424 28 010>mov dword ptr ss:[esp+28],1
00421BB3 . E8 98020000 call 22FAE.00421E50
00421BB8 . 8B03 mov eax,dword ptr ds:[ebx]
00421BBA . 8D4C24 14 lea ecx,dword ptr ss:[esp+14]
00421BBE . 50 push eax
00421BBF . 68 58C44200 push 22FAE.0042C458
; ASCII "UserName"
00421BC4 . E8 E7020000 call 22FAE.00421EB0
00421BC9 . 8B07 mov eax,dword ptr ds:[edi]
00421BCB . 8D4C24 14 lea ecx,dword ptr ss:[esp+14]
00421BCF . 50 push eax
00421BD0 . 68 4CC44200 push 22FAE.0042C44C
; ASCII "UserCode"
00421BD5 . E8 D6020000 call 22FAE.00421EB0
00421BDA . 53 push ebx
00421BDB . B9 70DC4200 mov ecx,22FAE.0042DC70
00421BE0 . C705 90E04200>mov dword ptr ds:[42E090],1
00421BEA . E8 170C0000 call <jmp.&mfc42.#858>
00421BEF . 57 push edi
00421BF0 . B9 34D04200 mov ecx,22FAE.0042D034
00421BF5 . E8 0C0C0000 call <jmp.&mfc42.#858>
00421BFA . 6A 00 push 0
00421BFC . 6A 00 push 0
00421BFE . 68 E8CC4200 push 22FAE.0042CCE8
; ASCII "Thank you for registering BitRecorder"
00421C03 . 8BCE mov ecx,esi
00421C05 . E8 46100000 call <jmp.&mfc42.#4224>
00421C0A . E8 8F0D0000 call <jmp.&mfc42.#1175>
00421C0F . 85C0 test eax,eax
00421C11 . 74 09 je short 22FAE.00421C1C
00421C13 . 8B10 mov edx,dword ptr ds:[eax]
00421C15 . 8BC8 mov ecx,eax
00421C17 . FF52 7C call dword ptr ds:[edx+7C]
00421C1A . EB 02 jmp short 22FAE.00421C1E
00421C1C > 33C0 xor eax,eax
00421C1E > 68 DCCC4200 push 22FAE.0042CCDC
; ASCII "BitRecorder"
00421C23 . 8BC8 mov ecx,eax
00421C25 . E8 A20F0000 call <jmp.&mfc42.#6199>
00421C2A . 8D4C24 14 lea ecx,dword ptr ss:[esp+14]
00421C2E . C74424 24 FFF>mov dword ptr ss:[esp+24],-1
00421C36 . E8 C5010000 call 22FAE.00421E00
00421C3B . 8BCE mov ecx,esi
00421C3D . E8 EE0B0000 call <jmp.&mfc42.#4853>
00421C42 . 8B4C24 1C mov ecx,dword ptr ss:[esp+1C]
00421C46 . 64:890D 00000>mov dword ptr fs:[0],ecx
00421C4D . 5F pop edi
00421C4E . 5E pop esi
00421C4F . 5B pop ebx
00421C50 . 83C4 1C add esp,1C
00421C53 . C3 retn
00421C54 > 6A 00 push 0
00421C56 . 6A 00 push 0
00421C58 . 68 C0CC4200 push 22FAE.0042CCC0
; ASCII "Sorry, the Code is error."
00421C5D . 8BCE mov ecx,esi
00421C5F . E8 EC0F0000 call <jmp.&mfc42.#4224>
00421C64 . 8B4C24 1C mov ecx,dword ptr ss:[esp+1C]
00421C68 . 5F pop edi
00421C69 . 5E pop esi
00421C6A . 64:890D 00000>mov dword ptr fs:[0],ecx
00421C71 . 5B pop ebx
00421C72 . 83C4 1C add esp,1C
00421C75 . C3 retn
-----------------------------------------------------------------
---------------
【算法过程】:
由注册码的第一位决定再在后面取相应数目的数字连到字符串"Bit-
Recorder-12"的前面再进行MD5加密计算,结果与注册码的剩余部分进行比
较,相符注册成功,不相符注册失败。注册与用户名无关。
-----------------------------------------------------------------
---------------
【经验总结】
-----------------------------------------------------------------
---------------
【版权声明】: 本文原创于萧萧黄叶, 转载请注明作者并保持文章的完整,
谢谢!
2009年06月
14日 0:47:14
【文章作者】: 萧萧黄叶
【作者邮箱】:
【作者主页】:
【作者QQ号】:
【软件名称】: BitRecorder1.61
【下载地址】: 自己搜索下载
【加壳方式】: ASPack 2.12 -> Alexey Solodovnikov
【保护方式】:
【编写语言】:
【使用工具】:
【操作平台】:
【软件介绍】:
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
-----------------------------------------------------------------
---------------
【详细过程】
先试运行程序,跳出对话框提示要注册,用假码注册看看有什么提示:“
Sorry, the Code is error.”
PEiD探壳:ASPack 2.12 -> Alexey Solodovnikov
一个很简单的压缩壳,用ESP定律找到OEP为22FAE进行脱壳,再用PEiD探
壳:Microsoft Visual C++ 6.0
并且程序能够正常运行。
C32Asm反汇编找到:
00421C58 PUSH 42CCC0 \->:
Sorry, the Code is error.
00421BFE PUSH 42CCE8 \->: Thank
you for registering BitRecorder
OK,用OD载入脱壳后的文件,程序停在这里:
00422FAE >/$ 55 push ebp
00422FAF |. 8BEC mov ebp,esp
00422FB1 |. 6A FF push -1
根据反汇编的提示在OD中下断点,运行程序,用假码注册,断在这里:
00421B30 . 6A FF push -1
00421B32 . 68 B0534200 push 22FAE.004253B0
; SE 处理程序安装
继续F8单步:
00421B37 . 64:A1 0000000>mov eax,dword ptr fs:[0]
00421B3D . 50 push eax
00421B3E . 64:8925 00000>mov dword ptr fs:[0],esp
00421B45 . 83EC 10 sub esp,10
00421B48 . 53 push ebx
00421B49 . 56 push esi
00421B4A . 57 push edi
00421B4B . 8BF1 mov esi,ecx
00421B4D . 6A 01 push 1
00421B4F . E8 E4100000 call <jmp.&mfc42.#6334>
00421B54 . 51 push ecx
; 经过上面这个CALL,用户名的后面一部分出现在寄存器EDX中
00421B55 . 8D7E 60 lea edi,dword ptr ds:[esi+60]
00421B58 . 8BCC mov ecx,esp
00421B5A . 896424 10 mov dword ptr ss:[esp+10],esp
00421B5E . 57 push edi
00421B5F . E8 B40C0000 call <jmp.&mfc42.#535>
00421B64 . 51 push ecx
; 经过上面这个CALL,注册码出现在堆栈中
00421B65 . 8D5E 64 lea ebx,dword ptr ds:[esi+64]
00421B68 . 8BCC mov ecx,esp
00421B6A . 896424 18 mov dword ptr ss:[esp+18],esp
00421B6E . 53 push ebx
00421B6F . C74424 30 000>mov dword ptr ss:[esp+30],0
00421B77 . E8 9C0C0000 call <jmp.&mfc42.#535>
00421B7C . C74424 2C FFF>mov dword ptr ss:[esp+2C],-1
; 经过上面这个CALL,用户名出现在堆栈中
00421B84 . E8 F7A5FEFF call 22FAE.0040C180
; 眼看着下面的跳转就要决定注册的成败,所以这里应该就是关键
CALL了,必须跟进!
00421B89 . 83C4 08 add esp,8
00421B8C . 85C0 test eax,eax
; 经过上面的CALL运算后如果EAX=0,下面的跳转就会实现,注册就
失败了。所以在关键CALL中要注意EAX的值。
0040C180 /$ 6A FF push -1
0040C182 |. 68 A83E4200 push 22FAE.00423EA8
; SE 处理程序安装
0040C187 |. 64:A1 0000000>mov eax,dword ptr fs:
[0]
0040C18D |. 50 push eax
0040C18E |. 64:8925 00000>mov dword ptr fs:
[0],esp
0040C195 |. 83EC 10 sub esp,10
0040C198 |. 53 push ebx
0040C199 |. 8D4C24 04 lea ecx,dword ptr ss:
[esp+4]
0040C19D |. C74424 1C 010>mov dword ptr ss:
[esp+1C],1
0040C1A5 |. E8 20660100 call <jmp.&mfc42.#540>
0040C1AA |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C1AE |. C64424 1C 02 mov byte ptr ss:
[esp+1C],2
0040C1B3 |. E8 12660100 call <jmp.&mfc42.#540>
0040C1B8 |. 8D4C24 08 lea ecx,dword ptr ss:
[esp+8]
0040C1BC |. C64424 1C 03 mov byte ptr ss:
[esp+1C],3
0040C1C1 |. E8 04660100 call <jmp.&mfc42.#540>
0040C1C6 |. 8B4424 28 mov eax,dword ptr ss:
[esp+28] ; 将注册码移动到EAX
0040C1CA |. B3 04 mov bl,4
0040C1CC |. 885C24 1C mov byte ptr ss:
[esp+1C],bl
0040C1D0 |. 8B40 F8 mov eax,dword ptr ds:
[eax-8] ; 取注册码的位数到EAX
0040C1D3 |. 85C0 test eax,eax
0040C1D5 |. 0F8E 78010000 jle 22FAE.0040C353
; 如果EAX为0,跳转实现,跳越计算,直接就毙了
0040C1DB |. 56 push esi
0040C1DC |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C1E0 |. 6A 01 push 1
0040C1E2 |. 51 push ecx
0040C1E3 |. 8D4C24 34 lea ecx,dword ptr ss:
[esp+34]
0040C1E7 |. E8 38660100 call
<jmp.&mfc42.#4129>
0040C1EC |. 8B00 mov eax,dword ptr ds:
[eax]
0040C1EE |. 50 push eax
; /s
0040C1EF |. FF15 48664200 call dword ptr ds:
[<&msvcrt.atoi>] ; \atoi
0040C1F5 |. 83C4 04 add esp,4
0040C1F8 |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C1FC |. 8BF0 mov esi,eax
0040C1FE |. E8 B5650100 call <jmp.&mfc42.#800>
0040C203 |. 8B5424 2C mov edx,dword ptr ss:
[esp+2C]
0040C207 |. 8D4C24 2C lea ecx,dword ptr ss:
[esp+2C]
0040C20B |. 8B42 F8 mov eax,dword ptr ds:
[edx-8]
0040C20E |. 48 dec eax
0040C20F |. 50 push eax
0040C210 |. 8D4424 18 lea eax,dword ptr ss:
[esp+18]
0040C214 |. 50 push eax
0040C215 |. E8 10660100 call
<jmp.&mfc42.#5710>
0040C21A |. 50 push eax
0040C21B |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C21F |. C64424 24 05 mov byte ptr ss:
[esp+24],5
0040C224 |. E8 DD650100 call <jmp.&mfc42.#858>
0040C229 |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C22D |. 885C24 20 mov byte ptr ss:
[esp+20],bl
0040C231 |. E8 82650100 call <jmp.&mfc42.#800>
0040C236 |. 8B4C24 2C mov ecx,dword ptr ss:
[esp+2C]
0040C23A |. 8D5424 14 lea edx,dword ptr ss:
[esp+14]
0040C23E |. 8B41 F8 mov eax,dword ptr ds:
[ecx-8]
0040C241 |. 8D4C24 2C lea ecx,dword ptr ss:
[esp+2C]
0040C245 |. 2BC6 sub eax,esi
0040C247 |. 48 dec eax
0040C248 |. 50 push eax
0040C249 |. 52 push edx
0040C24A |. E8 DB650100 call
<jmp.&mfc42.#5710>
0040C24F |. 50 push eax
0040C250 |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C254 |. C64424 24 06 mov byte ptr ss:
[esp+24],6
0040C259 |. E8 A8650100 call <jmp.&mfc42.#858>
0040C25E |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C262 |. 885C24 20 mov byte ptr ss:
[esp+20],bl
0040C266 |. E8 4D650100 call <jmp.&mfc42.#800>
0040C26B |. 8D4424 14 lea eax,dword ptr ss:
[esp+14]
0040C26F |. 56 push esi
0040C270 |. 50 push eax
0040C271 |. 8D4C24 10 lea ecx,dword ptr ss:
[esp+10]
0040C275 |. E8 AA650100 call
<jmp.&mfc42.#4129>
0040C27A |. 50 push eax
0040C27B |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C27F |. C64424 24 07 mov byte ptr ss:
[esp+24],7
0040C284 |. E8 7D650100 call <jmp.&mfc42.#858>
0040C289 |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C28D |. 885C24 20 mov byte ptr ss:
[esp+20],bl
0040C291 |. E8 22650100 call <jmp.&mfc42.#800>
0040C296 |. 8D4C24 08 lea ecx,dword ptr ss:
[esp+8]
0040C29A |. 68 8CC24200 push 22FAE.0042C28C
; ASCII "Bit-Recorder-12"这是一个固定字符
0040C29F |. 8D5424 18 lea edx,dword ptr ss:
[esp+18]
0040C2A3 |. 51 push ecx
0040C2A4 |. 52 push edx
0040C2A5 |. E8 CE680100 call <jmp.&mfc42.#924>
; 由注册码的第一位决定后面取相应数目的数字并连
到上面的固定字符的前面
0040C2AA |. 50 push eax
0040C2AB |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C2AF |. C64424 24 08 mov byte ptr ss:
[esp+24],8
0040C2B4 |. E8 4D650100 call <jmp.&mfc42.#858>
0040C2B9 |. 8D4C24 14 lea ecx,dword ptr ss:
[esp+14]
0040C2BD |. 885C24 20 mov byte ptr ss:
[esp+20],bl
0040C2C1 |. E8 F2640100 call <jmp.&mfc42.#800>
0040C2C6 |. 8B4424 08 mov eax,dword ptr ss:
[esp+8]
0040C2CA |. 50 push eax
0040C2CB |. E8 D0300100 call 22FAE.0041F3A0
; 这个CALL是对刚才加工后的字符串进行了MD5加密。
0040C2D0 |. 83C4 04 add esp,4
0040C2D3 |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C2D7 |. 50 push eax
0040C2D8 |. E8 35650100 call <jmp.&mfc42.#860>
0040C2DD |. 8B4C24 0C mov ecx,dword ptr ss:
[esp+C]
0040C2E1 |. 8B5424 10 mov edx,dword ptr ss:
[esp+10] ; 下面的S1等于注册码除去前两位后面的剩余部分
,S1等于MD5加密值。再下面的CALL从字面上理解就是CMP,比较了。
0040C2E5 |. 51 push ecx
; /s2
0040C2E6 |. 52 push edx
; |s1
0040C2E7 |. FF15 3C664200 call dword ptr ds:
[<&msvcrt._mbscmp>] ; \_mbscmp
77C01881 > 8BFF mov
edi,edi
77C01883 55 push ebp
77C01884 8BEC mov
ebp,esp
77C01886 56 push esi
77C01887 E8 99860000 call
msvcrt.77C09F25
77C0188C 8B70 60 mov
esi,dword ptr ds:[eax+60]
77C0188F 3B35 4425C377 cmp
esi,dword ptr ds:[77C32544]
77C01895 74 07 je short
msvcrt.77C0189E
77C01897 E8 91EDFFFF call
msvcrt.77C0062D
77C0189C 8BF0 mov
esi,eax
77C0189E 837E 08 00 cmp
dword ptr ds:[esi+8],0
77C018A2 75 2F jnz
short msvcrt.77C018D3
77C018A4 8B75 0C mov
esi,dword ptr ss:[ebp+C]
77C018A7 8B45 08 mov
eax,dword ptr ss:[ebp+8]
77C018AA 8A10 mov
dl,byte ptr ds:[eax]
77C018AC 8ACA mov
cl,dl
77C018AE 3A16 cmp
dl,byte ptr ds:[esi]
77C018B0 75 1A jnz
short msvcrt.77C018CC
77C018B2 84C9 test
cl,cl
77C018B4 74 12 je short
msvcrt.77C018C8
77C018B6 8A50 01 mov
dl,byte ptr ds:[eax+1]
77C018B9 8ACA mov
cl,dl
77C018BB 3A56 01 cmp
dl,byte ptr ds:[esi+1]
77C018BE 75 0C jnz
short msvcrt.77C018CC
77C018C0 40 inc eax
77C018C1 40 inc eax
77C018C2 46 inc esi
77C018C3 46 inc esi
77C018C4 84C9 test
cl,cl
77C018C6 ^ 75 E2 jnz
short msvcrt.77C018AA
77C018C8 33C0 xor
eax,eax
77C018CA EB 68 jmp
short msvcrt.77C01934
77C018CC 1BC0 sbb
eax,eax
77C018CE 83D8 FF sbb
eax,-1
77C018D1 EB 61 jmp
short msvcrt.77C01934
77C018D3 57 push edi
77C018D4 8B7D 0C mov
edi,dword ptr ss:[ebp+C]
77C018D7 53 push ebx
77C018D8 8B45 08 mov
eax,dword ptr ss:[ebp+8]
77C018DB 66:0FB600 movzx
ax,byte ptr ds:[eax] ; 取加工后的注册码的第一位的ASC
码到AX
77C018DF FF45 08 inc
dword ptr ss:[ebp+8]
77C018E2 0FB6C8 movzx
ecx,al
77C018E5 F64431 1D 04 test
byte ptr ds:[ecx+esi+1D],4
77C018EA 74 18 je short
msvcrt.77C01904
77C018EC 8B4D 08 mov
ecx,dword ptr ss:[ebp+8]
77C018EF 8A09 mov
cl,byte ptr ds:[ecx]
77C018F1 84C9 test
cl,cl
77C018F3 75 04 jnz
short msvcrt.77C018F9
77C018F5 33C0 xor
eax,eax
77C018F7 EB 0B jmp
short msvcrt.77C01904
77C018F9 33D2 xor
edx,edx
77C018FB FF45 08 inc
dword ptr ss:[ebp+8]
77C018FE 8AF0 mov
dh,al
77C01900 8AD1 mov
dl,cl
77C01902 8BC2 mov
eax,edx
77C01904 66:0FB60F movzx
cx,byte ptr ds:[edi] ; 取MD5加密值的第一位的ASC码到
CX
77C01908 0FB6D1 movzx
edx,cl
77C0190B 47 inc edi
77C0190C F64432 1D 04 test
byte ptr ds:[edx+esi+1D],4
77C01911 74 13 je short
msvcrt.77C01926
77C01913 8A17 mov
dl,byte ptr ds:[edi]
77C01915 84D2 test
dl,dl
77C01917 75 04 jnz
short msvcrt.77C0191D
77C01919 33C9 xor
ecx,ecx
77C0191B EB 09 jmp
short msvcrt.77C01926
77C0191D 33DB xor
ebx,ebx
77C0191F 8AF9 mov
bh,cl
77C01921 47 inc edi
77C01922 8ADA mov
bl,dl
77C01924 8BCB mov
ecx,ebx
77C01926 66:3BC8 cmp
cx,ax ; AX与CX进行比较,相等下面的
跳转就不跳,在返回之前会将EAX清零;否则跳转实现
77C01929 75 0C jnz
short msvcrt.77C01937
77C0192B 66:85C0 test
ax,ax
77C0192E ^ 75 A8 jnz
short msvcrt.77C018D8
77C01930 33C0 xor
eax,eax
77C01932 5B pop ebx
77C01933 5F pop edi
77C01934 5E pop esi
77C01935 5D pop ebp
77C01936 C3 retn
77C01937 1BC0 sbb
eax,eax ; 如果跳转到这里,会使EAX=1
77C01939 83E0 02 and
eax,2
77C0193C 48 dec eax
77C0193D ^ EB F3 jmp
short msvcrt.77C01932
0040C2ED |. 83C4 08 add esp,8
0040C2F0 |. C64424 20 03 mov byte ptr ss:
[esp+20],3
0040C2F5 |. 85C0 test eax,eax
0040C2F7 |. 5E pop esi
0040C2F8 |. 8D4C24 08 lea ecx,dword ptr ss:
[esp+8]
0040C2FC |. 75 5E jnz short
22FAE.0040C35C ; EAX的值将决定这里的跳转。一跳就
死!
0040C2FE |. E8 B5640100 call <jmp.&mfc42.#800>
0040C303 |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C307 |. C64424 1C 02 mov byte ptr ss:
[esp+1C],2
0040C30C |. E8 A7640100 call <jmp.&mfc42.#800>
0040C311 |. 8D4C24 04 lea ecx,dword ptr ss:
[esp+4]
0040C315 |. C64424 1C 01 mov byte ptr ss:
[esp+1C],1
0040C31A |. E8 99640100 call <jmp.&mfc42.#800>
0040C31F |. 8D4C24 24 lea ecx,dword ptr ss:
[esp+24]
0040C323 |. C64424 1C 00 mov byte ptr ss:
[esp+1C],0
0040C328 |. E8 8B640100 call <jmp.&mfc42.#800>
0040C32D |. 8D4C24 28 lea ecx,dword ptr ss:
[esp+28]
0040C331 |. C74424 1C FFF>mov dword ptr ss:
[esp+1C],-1
0040C339 |. E8 7A640100 call <jmp.&mfc42.#800>
0040C33E |. B8 01000000 mov eax,1
; 这里会给EAX赋值为1
0040C343 |. 5B pop ebx
0040C344 |. 8B4C24 10 mov ecx,dword ptr ss:
[esp+10]
0040C348 |. 64:890D 00000>mov dword ptr fs:
[0],ecx
0040C34F |. 83C4 1C add esp,1C
0040C352 |. C3 retn
0040C353 |> C64424 1C 03 mov byte ptr ss:
[esp+1C],3
0040C358 |. 8D4C24 08 lea ecx,dword ptr ss:
[esp+8]
0040C35C |> E8 57640100 call <jmp.&mfc42.#800>
0040C361 |. 8D4C24 0C lea ecx,dword ptr ss:
[esp+C]
0040C365 |. C64424 1C 02 mov byte ptr ss:
[esp+1C],2
0040C36A |. E8 49640100 call <jmp.&mfc42.#800>
0040C36F |. 8D4C24 04 lea ecx,dword ptr ss:
[esp+4]
0040C373 |. C64424 1C 01 mov byte ptr ss:
[esp+1C],1
0040C378 |. E8 3B640100 call <jmp.&mfc42.#800>
0040C37D |. 8D4C24 24 lea ecx,dword ptr ss:
[esp+24]
0040C381 |. C64424 1C 00 mov byte ptr ss:
[esp+1C],0
0040C386 |. E8 2D640100 call <jmp.&mfc42.#800>
0040C38B |. 8D4C24 28 lea ecx,dword ptr ss:
[esp+28]
0040C38F |. C74424 1C FFF>mov dword ptr ss:
[esp+1C],-1
0040C397 |. E8 1C640100 call <jmp.&mfc42.#800>
0040C39C |. 8B4C24 14 mov ecx,dword ptr ss:
[esp+14]
0040C3A0 |. 33C0 xor eax,eax
; 这里是将EAX清零
0040C3A2 |. 5B pop ebx
0040C3A3 |. 64:890D 00000>mov dword ptr fs:
[0],ecx
0040C3AA |. 83C4 1C add esp,1C
0040C3AD \. C3 retn
00421B8E . 0F84 C0000000 je 22FAE.00421C54
; 关键跳,一跳就死!
00421B94 . 68 01000080 push 80000001
00421B99 . 8D4C24 18 lea ecx,dword ptr ss:[esp+18]
00421B9D . E8 1E020000 call 22FAE.00421DC0
00421BA2 . 68 64C44200 push 22FAE.0042C464
; ASCII "SOFTWARE\BitRecorder"
00421BA7 . 8D4C24 18 lea ecx,dword ptr ss:[esp+18]
00421BAB . C74424 28 010>mov dword ptr ss:[esp+28],1
00421BB3 . E8 98020000 call 22FAE.00421E50
00421BB8 . 8B03 mov eax,dword ptr ds:[ebx]
00421BBA . 8D4C24 14 lea ecx,dword ptr ss:[esp+14]
00421BBE . 50 push eax
00421BBF . 68 58C44200 push 22FAE.0042C458
; ASCII "UserName"
00421BC4 . E8 E7020000 call 22FAE.00421EB0
00421BC9 . 8B07 mov eax,dword ptr ds:[edi]
00421BCB . 8D4C24 14 lea ecx,dword ptr ss:[esp+14]
00421BCF . 50 push eax
00421BD0 . 68 4CC44200 push 22FAE.0042C44C
; ASCII "UserCode"
00421BD5 . E8 D6020000 call 22FAE.00421EB0
00421BDA . 53 push ebx
00421BDB . B9 70DC4200 mov ecx,22FAE.0042DC70
00421BE0 . C705 90E04200>mov dword ptr ds:[42E090],1
00421BEA . E8 170C0000 call <jmp.&mfc42.#858>
00421BEF . 57 push edi
00421BF0 . B9 34D04200 mov ecx,22FAE.0042D034
00421BF5 . E8 0C0C0000 call <jmp.&mfc42.#858>
00421BFA . 6A 00 push 0
00421BFC . 6A 00 push 0
00421BFE . 68 E8CC4200 push 22FAE.0042CCE8
; ASCII "Thank you for registering BitRecorder"
00421C03 . 8BCE mov ecx,esi
00421C05 . E8 46100000 call <jmp.&mfc42.#4224>
00421C0A . E8 8F0D0000 call <jmp.&mfc42.#1175>
00421C0F . 85C0 test eax,eax
00421C11 . 74 09 je short 22FAE.00421C1C
00421C13 . 8B10 mov edx,dword ptr ds:[eax]
00421C15 . 8BC8 mov ecx,eax
00421C17 . FF52 7C call dword ptr ds:[edx+7C]
00421C1A . EB 02 jmp short 22FAE.00421C1E
00421C1C > 33C0 xor eax,eax
00421C1E > 68 DCCC4200 push 22FAE.0042CCDC
; ASCII "BitRecorder"
00421C23 . 8BC8 mov ecx,eax
00421C25 . E8 A20F0000 call <jmp.&mfc42.#6199>
00421C2A . 8D4C24 14 lea ecx,dword ptr ss:[esp+14]
00421C2E . C74424 24 FFF>mov dword ptr ss:[esp+24],-1
00421C36 . E8 C5010000 call 22FAE.00421E00
00421C3B . 8BCE mov ecx,esi
00421C3D . E8 EE0B0000 call <jmp.&mfc42.#4853>
00421C42 . 8B4C24 1C mov ecx,dword ptr ss:[esp+1C]
00421C46 . 64:890D 00000>mov dword ptr fs:[0],ecx
00421C4D . 5F pop edi
00421C4E . 5E pop esi
00421C4F . 5B pop ebx
00421C50 . 83C4 1C add esp,1C
00421C53 . C3 retn
00421C54 > 6A 00 push 0
00421C56 . 6A 00 push 0
00421C58 . 68 C0CC4200 push 22FAE.0042CCC0
; ASCII "Sorry, the Code is error."
00421C5D . 8BCE mov ecx,esi
00421C5F . E8 EC0F0000 call <jmp.&mfc42.#4224>
00421C64 . 8B4C24 1C mov ecx,dword ptr ss:[esp+1C]
00421C68 . 5F pop edi
00421C69 . 5E pop esi
00421C6A . 64:890D 00000>mov dword ptr fs:[0],ecx
00421C71 . 5B pop ebx
00421C72 . 83C4 1C add esp,1C
00421C75 . C3 retn
-----------------------------------------------------------------
---------------
【算法过程】:
由注册码的第一位决定再在后面取相应数目的数字连到字符串"Bit-
Recorder-12"的前面再进行MD5加密计算,结果与注册码的剩余部分进行比
较,相符注册成功,不相符注册失败。注册与用户名无关。
-----------------------------------------------------------------
---------------
【经验总结】
-----------------------------------------------------------------
---------------
【版权声明】: 本文原创于萧萧黄叶, 转载请注明作者并保持文章的完整,
谢谢!
2009年06月
14日 0:47:14
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: