#目标软件:网际飞音(如果是云南的朋友在看贴就不用多说了。不过还是要介绍一下这一款软件是很好的多媒体播放软件,但是只有该软件才
# 可以播放music.km169.net上的歌曲。)
#
#逆向目的:跟踪出她的解密方法,用C语言实现在linux下的伪移植^.^
#
#必杀武器:Ollydgb,VI,GCC
#
#看T须知:请大家不要将此帖转发到任何其他网站,或论坛。大家还要注意看帖要回帖,上完厕所要冲水,路边捡到钱要交给警察叔叔^.^
#
#
#
这是一篇逆向跟踪网际飞音编码过的歌曲url地址的解码过程,从而编写出一个解码器,使music.km169.net上面的歌曲能够在linux下用Mplayer来在线播放。
00402810 /$ 83EC 08 sub esp,8
00402813 |. 8D4424 00 lea eax,dword ptr ss:[esp]
00402817 |. 56 push esi
00402818 |. 8B7424 10 mov esi,dword ptr ss:[esp+10]
0040281C |. 57 push edi
0040281D |. 6A 02 push 2
0040281F |. 6A 07 push 7
00402821 |. 50 push eax
00402822 |. 8BCE mov ecx,esi
00402824 |. E8 F7C90200 call donor.0042F220
00402829 |. 8B3D 28F24300 mov edi,dword ptr ds:[<&KERNEL32.lstrcmpA>] ; kernel32.lstrcmpA
0040282F |. 8D4C24 08 lea ecx,dword ptr ss:[esp+8]
00402833 |. 68 BC514400 push donor.004451BC ; /String2 = "01"
00402838 |. 51 push ecx ; |String1
00402839 |. FFD7 call edi ; \lstrcmpA
0040283B |. 85C0 test eax,eax
0040283D |. 75 0F jnz short donor.0040284E
0040283F |. 56 push esi
00402840 |. E8 5B060000 call donor.00402EA0 ; 这一句就是关键的call,跟进对解密详细的分析
00402845 |. 83C4 04 add esp,4
00402848 |. 5F pop edi
00402849 |. 5E pop esi
0040284A |. 83C4 08 add esp,8
0040284D |. C3 retn
00402EA0 /$ 6A FF push -1
00402EA2 |. 68 A8BD4300 push donor.0043BDA8
00402EA7 |. 64:A1 00000000 mov eax,dword ptr fs:[0]
00402EAD |. 50 push eax
00402EAE |. 64:8925 00000000 mov dword ptr fs:[0],esp
00402EB5 |. 83EC 0C sub esp,0C
00402EB8 |. 53 push ebx
00402EB9 |. 55 push ebp
00402EBA |. 56 push esi
00402EBB |. 57 push edi
00402EBC |. 8D4C24 10 lea ecx,dword ptr ss:[esp+10]
00402EC0 |. E8 8BC00200 call donor.0042EF50
00402EC5 |. 68 00080000 push 800
00402ECA |. C74424 28 00000000 mov dword ptr ss:[esp+28],0
00402ED2 |. E8 34E80200 call donor.0043170B ;这一部分作用是在系统中申请一部分内存空间以备后用
00402ED7 |. 68 00040000 push 400
00402EDC |. 8BF8 mov edi,eax
00402EDE |. E8 28E80200 call donor.0043170B
00402EE3 |. 8B7424 34 mov esi,dword ptr ss:[esp+34]
00402EE7 |. 83C4 08 add esp,8
00432AD8 > \8B45 08 mov eax,dword ptr ss:[ebp+8] 从43170B跟进就可以发现在这里是分配堆空间的
00432ADB . 85C0 test eax,eax
00432ADD . 75 03 jnz short donor.00432AE2
00432ADF . 6A 01 push 1
00432AE1 . 58 pop eax
00432AE2 > 83C0 0F add eax,0F
00432AE5 . 24 F0 and al,0F0
00432AE7 . 50 push eax
00432AE8 > 6A 00 push 0 ; |Flags = 0
00432AEA . FF35 E0E84400 push dword ptr ds:[44E8E0] ; |hHeap = 003F0000
00432AF0 . FF15 A8F14300 call dword ptr ds:[<&KERNEL32.HeapAlloc>] ; \HeapAlloc
00432AF6 > 8B4D F0 mov ecx,dword ptr ss:[ebp-10]
00432AF9 . 64:890D 00000000 mov dword ptr fs:[0],ecx
00432B00 . 5F pop edi
00432B01 . 5E pop esi
00432B02 . 5B pop ebx
00432B03 . C9 leave
00432B04 . C3 retn ;不用细看,可以直接返回到43170B的下一条指令继续跟踪
这里一看就知道肯定是对字符处理的部分了,不过这还只是第一部分,不能高兴得太早。先跟进42F3A0看看
00402EEE |. 6A 30 push 30 0<====>C
00402EF0 |. 6A 43 push 43
00402EF2 |. E8 A9C40200 call donor.0042F3A0
00402EF7 |. 6A 31 push 31 1<====>D
00402EF9 |. 6A 44 push 44
00402EFB |. 8BCE mov ecx,esi
00402EFD |. E8 9EC40200 call donor.0042F3A0
00402F02 |. 6A 32 push 32 2<====>E
00402F04 |. 6A 45 push 45
00402F06 |. 8BCE mov ecx,esi
00402F08 |. E8 93C40200 call donor.0042F3A0
00402F0D |. 6A 33 push 33 3<====>F
00402F0F |. 6A 46 push 46
00402F11 |. 8BCE mov ecx,esi
00402F13 |. E8 88C40200 call donor.0042F3A0
00402F18 |. 6A 34 push 34 4<====>G
00402F1A |. 6A 47 push 47
00402F1C |. 8BCE mov ecx,esi
00402F1E |. E8 7DC40200 call donor.0042F3A0
00402F23 |. 6A 35 push 35 5<====>A
00402F25 |. 6A 41 push 41
00402F27 |. 8BCE mov ecx,esi
00402F29 |. E8 72C40200 call donor.0042F3A0
00402F2E |. 6A 36 push 36 6<====>B
00402F30 |. 6A 42 push 42
00402F32 |. 8BCE mov ecx,esi
00402F34 |. E8 67C40200 call donor.0042F3A0
00402F39 |. 6A 37 push 37 7<====>Z
00402F3B |. 6A 5A push 5A
00402F3D |. 8BCE mov ecx,esi
00402F3F |. E8 5CC40200 call donor.0042F3A0
00402F44 |. 6A 38 push 38 8<====>I
00402F46 |. 6A 49 push 49
00402F48 |. 8BCE mov ecx,esi
00402F4A |. E8 51C40200 call donor.0042F3A0
00402F4F |. 6A 39 push 39 9<====>P
00402F51 |. 6A 50 push 50
00402F53 |. 8BCE mov ecx,esi
00402F55 |. E8 46C40200 call donor.0042F3A0
00402F5A |. 6A 41 push 41 A<====>O
00402F5C |. 6A 4F push 4F
00402F5E |. 8BCE mov ecx,esi
00402F60 |. E8 3BC40200 call donor.0042F3A0
00402F65 |. 6A 42 push 42 B<====>R
00402F67 |. 6A 52 push 52
00402F69 |. 8BCE mov ecx,esi
00402F6B |. E8 30C40200 call donor.0042F3A0
00402F70 |. 6A 43 push 43 C<====>N
00402F72 |. 6A 4E push 4E
00402F74 |. 8BCE mov ecx,esi
00402F76 |. E8 25C40200 call donor.0042F3A0
00402F7B |. 6A 44 push 44 D<====>L
00402F7D |. 6A 4C push 4C
00402F7F |. 8BCE mov ecx,esi
00402F81 |. E8 1AC40200 call donor.0042F3A0
00402F86 |. 6A 45 push 45 E<====>K
00402F88 |. 6A 4B push 4B
00402F8A |. 8BCE mov ecx,esi
00402F8C |. E8 0FC40200 call donor.0042F3A0
00402F91 |. 6A 46 push 46 F<====>T
00402F93 |. 6A 54 push 54
00402F95 |. 8BCE mov ecx,esi
00402F97 |. E8 04C40200 call donor.0042F3A0
0042F3A0 /$ 8B41 08 mov eax,dword ptr ds:[ecx+8] ;将字符串的个数放入eax寄存器中
0042F3A3 |. 56 push esi
0042F3A4 |. 57 push edi
0042F3A5 |. 33FF xor edi,edi
0042F3A7 |. 33F6 xor esi,esi
0042F3A9 |. 85C0 test eax,eax ;检测字符串是否为空
0042F3AB |. 7E 2A jle short donor.0042F3D7 ;是就跳了
0042F3AD |. 8A4424 10 mov al,byte ptr ss:[esp+10] ;目标字符放入eax寄存器待用
0042F3B1 |. 53 push ebx
0042F3B2 |. 55 push ebp
0042F3B3 |. 8B6C24 14 mov ebp,dword ptr ss:[esp+14]
0042F3B7 |> 8B51 04 /mov edx,dword ptr ds:[ecx+4] ; 得到待处理字符串的地址
0042F3BA |. 03D6 |add edx,esi
0042F3BC |. 0FBE1A |movsx ebx,byte ptr ds:[edx] ;取出字符串的每个字符,edx相当于一个累加器
0042F3BF |. 3BDD |cmp ebx,ebp ;与特征字符作比较。
0042F3C1 |. 75 03 |jnz short donor.0042F3C6 ;如果不同则跳到下面继续
0042F3C3 |. 8802 |mov byte ptr ds:[edx],al ;如果相同,则用目标字符替换该特征字符
0042F3C5 |. 47 |inc edi ;edi相当于一个计数器,记录被转换了的字符个数
0042F3C6 |> 8B51 08 |mov edx,dword ptr ds:[ecx+8] ;取得字符串字符个数,检测是否到了字符串尾,
0042F3C9 |. 46 |inc esi ;是则跳出,否则就循环
0042F3CA |. 3BF2 |cmp esi,edx
0042F3CC |.^ 7C E9 \jl short donor.0042F3B7
0042F3CE |. 5D pop ebp
0042F3CF |. 8BC7 mov eax,edi ; eax为互换后的个数
0042F3D1 |. 5B pop ebx
0042F3D2 |. 5F pop edi
0042F3D3 |. 5E pop esi
0042F3D4 |. C2 0800 retn 8
00402FE5 |> \8BCE mov ecx,esi
00402FE7 |. E8 C4C70200 call donor.0042F7B0
00402FEC |. B9 F6FFFFFF mov ecx,-0A
00402FF1 |. 2BCB sub ecx,ebx
00402FF3 |. 83C3 09 add ebx,9
00402FF6 |. 03C1 add eax,ecx
00402FF8 |. 8BCE mov ecx,esi
00402FFA |. 50 push eax
00402FFB |. 53 push ebx
00402FFC |. 57 push edi
00402FFD |. E8 1EC20200 call donor.0042F220 ;第二次解码的入口
00403002 |. 57 push edi
00403003 |. 8BCE mov ecx,esi
00403005 |. E8 76C00200 call donor.0042F080
0040300A |. 8BCE mov ecx,esi
0040300C |. E8 CFC30200 call donor.0042F3E0 ;在这里进行具体的解码工作
00403011 |. 68 88D04400 push donor.0044D088
00403016 |. 8D4C24 14 lea ecx,dword ptr ss:[esp+14]
0040301A |. E8 61C00200 call donor.0042F080
0040301F |. 33DB xor ebx,ebx
0042F220 /$ 53 push ebx
0042F221 |. 56 push esi ;这一部分依然是对字符串的长度做出判断。
0042F222 |. 8B7424 10 mov esi,dword ptr ss:[esp+10]
0042F226 |. 57 push edi
0042F227 |. 8BF9 mov edi,ecx
0042F229 |. 3B77 08 cmp esi,dword ptr ds:[edi+8]
0042F22C |. 7E 08 jle short donor.0042F236
0042F22E |. 5F pop edi
0042F22F |. 5E pop esi
0042F230 |. 33C0 xor eax,eax
0042F232 |. 5B pop ebx
0042F233 |. C2 0C00 retn 0C
0042F236 |> 8B5C24 18 mov ebx,dword ptr ss:[esp+18]
0042F23A |. 83FB FF cmp ebx,-1
0042F23D |. 75 1C jnz short donor.0042F25B
0042F25B |> \8B47 04 mov eax,dword ptr ds:[edi+4] ;这里用于去掉字符串中无意义的字符串
0042F25E |. 8B4C24 10 mov ecx,dword ptr ss:[esp+10] ;也就是dnmp://这些,具体的有17个无用字符
0042F262 |. 8D53 01 lea edx,dword ptr ds:[ebx+1]
0042F265 |. 03C6 add eax,esi
0042F267 |. 52 push edx ; /n
0042F268 |. 50 push eax ; |String2
0042F269 |. 51 push ecx ; |String1
0042F26A |. FF15 C8F04300 call dword ptr ds:[<&KERNEL32.lstrcpynA>] ; \lstrcpynA
0042F3E0 /$ 55 push ebp
0042F3E1 |. 56 push esi
0042F3E2 |. 57 push edi
0042F3E3 |. 8B79 08 mov edi,dword ptr ds:[ecx+8]
0042F3E6 |. 4F dec edi
0042F3E7 |. 33F6 xor esi,esi
0042F3E9 |. 8BC7 mov eax,edi
0042F3EB |. 99 cdq
0042F3EC |. 2BC2 sub eax,edx
0042F3EE |. 8BE8 mov ebp,eax
0042F3F0 |. D1FD sar ebp,1
0042F3F2 |. 78 20 js short donor.0042F414
0042F3F4 |. 53 push ebx
0042F3F5 |> 8B51 04 /mov edx,dword ptr ds:[ecx+4] ; 字符串取反
0042F3F8 |. 8BDA |mov ebx,edx
0042F3FA |. 0FBE0432 |movsx eax,byte ptr ds:[edx+esi] ;
0042F3FE |. 2BDE |sub ebx,esi
0042F400 |. 8A1C3B |mov bl,byte ptr ds:[ebx+edi] ;循环得到下一个字符
0042F403 |. 881C32 |mov byte ptr ds:[edx+esi],bl ;放入目标字符串中
0042F406 |. 8B51 04 |mov edx,dword ptr ds:[ecx+4]
0042F409 |. 2BD6 |sub edx,esi
0042F40B |. 46 |inc esi
0042F40C |. 3BF5 |cmp esi,ebp
0042F40E |. 88043A |mov byte ptr ds:[edx+edi],al
0042F411 |.^ 7E E2 \jle short donor.0042F3F5
0042F413 |. 5B pop ebx
0042F414 |> 5F pop edi
0042F415 |. 5E pop esi
0042F416 |. 5D pop ebp
0042F417 \. C3 retn
0040302C |. 48 dec eax ;来到这里也到了解码的最后一步了
0040302D |. 85C0 test eax,eax
0040302F |. 7E 4F jle short donor.00403080
00403031 |> 6A 02 /push 2
00403033 |. 53 |push ebx
00403034 |. 57 |push edi
00403035 |. 8BCE |mov ecx,esi
00403037 |. E8 E4C10200 |call donor.0042F220
0040303C |. 8A07 |mov al,byte ptr ds:[edi] ;循环取字符串的下一个奇数字符
0040303E |. 3C 41 |cmp al,41 ;比较是否大于‘A’
00403040 |. 0FBEC0 |movsx eax,al ;先将字符保存
00403043 |. 7C 05 |jl short donor.0040304A ;如果小于就减去30,大于等于就减去37。也就相
00403045 |. 83E8 37 |sub eax,37 ;当于ascii编码的数字被转化为相应的Hex值
00403048 |. EB 03 |jmp short donor.0040304D
0040304A |> 83E8 30 |sub eax,30
0040304D |> 8A4F 01 |mov cl,byte ptr ds:[edi+1] ;循环取字符串的下一个偶数字符
00403050 |. 80F9 41 |cmp cl,41
00403053 |. 0FBEC9 |movsx ecx,cl
00403056 |. 7C 05 |jl short donor.0040305D
00403058 |. 83E9 37 |sub ecx,37
0040305B |. EB 03 |jmp short donor.00403060
0040305D |> 83E9 30 |sub ecx,30 ;同上作相应处理
00403060 |> C0E0 04 |shl al,4 ;左移4位,也就是乘于2的4次方等于乘于16
00403063 |. 02C1 |add al,cl ;将两个字符组合为一个新的ascii字符
00403065 |. 8B4C24 2C |mov ecx,dword ptr ss:[esp+2C]
00403069 |. 83C3 02 |add ebx,2
0040306C |. 880429 |mov byte ptr ds:[ecx+ebp],al ;之后就是判断循环的条件了。
0040306F |. 41 |inc ecx
00403070 |. 894C24 2C |mov dword ptr ss:[esp+2C],ecx
00403074 |. 8BCE |mov ecx,esi
00403076 |. E8 35C70200 |call donor.0042F7B0
0040307B |. 48 |dec eax
0040307C |. 3BD8 |cmp ebx,eax
0040307E |.^ 7C B1 \jl short donor.00403031
至此,整个解码过程已经最终完成了。但是这里解码出来的字符串里面除了包含歌曲的url以外,还包括了一些我们所不需要的信息。不过这些无用的信息都可以编程将其去掉。以下就是我的C语言源代码。注意:使用这个程序的前提是你的linux系统上已经安装有了Mplayer。
以下是程序源代码,写得很乱,也没有做任何的优化,先凑合着用.考了试再进一步做修改,如果有用linux的朋友有兴趣可以一起研究研究.
####################################################################################################################################################
/* music online v0.1 */
/* code by xeno */
/*email: xeno2cc@sohu.com*/
/* 2005.7.7 */
#include "stdio.h"
#include "stdlib.h"
int GetString (char ts[7], FILE * s);
void DeCode (char txt[230], int n);
char *ab;
int count = 0, lg;
main (int argc, char *argv[])
{
char cds[230] = "", ts[7] = "<media", mp[200] = "mplayer ";
FILE *s;
int n = 1, i;
if ((s = fopen (argv[1], "r")) == NULL)
printf ("file open failed\n");
while (n != 0)
{
rewind (s);
n = GetString (ts, s);
if (n == 0)
break;
strcpy (cds, ab);
for (i = 0; i <= lg; i++)
mp[8 + i] = cds[i];
printf ("%s\n", mp);
system (mp);
}
fclose (s);
exit (0);
}
int
GetString (char ts[7], FILE * s)
{
int j, n = 0, flag = 0, chs = 1;
char cd, cs[7] = "", name[230] = "";
fseek (s, 0, 2);
j = ftell (s);
rewind (s);
if (count < j)
{
while (chs != 0)
{
fseek (s, count, 0);
j = fgets (cs, 7, s);
if (j == 0)
return 0;
count++;
if (strcmp (cs, ts) == 0) /*取得指定字符串 */
{
while (flag != 2)
{
cd = fgetc (s);
if (cd == 34)
flag++;
while (flag == 1)
{
cd = fgetc (s);
if (cd == 34)
{
flag++;
break;
}
name[n] = cd;
n++;
}
}
if (n % 2 == 1)
name[n] = 0;
chs = 0;
flag = 0;
}
}
}
DeCode (name, n);
return j;
}
void
DeCode (char txt[230], int n) /*字符对比代换 */
{
char a[230], m[76] = "";
int i, ah, d = 0, al, z;
for (i = 0; i <= n; i++)
{
switch (txt[i])
{
case 'C':
txt[i] = '0';
break;
case 'D':
txt[i] = '1';
break;
case 'E':
txt[i] = '2';
break;
case 'F':
txt[i] = '3';
break;
case 'G':
txt[i] = '4';
break;
case 'A':
txt[i] = '5';
break;
case 'B':
txt[i] = '6';
break;
case 'Z':
txt[i] = '7';
break;
case 'I':
txt[i] = '8';
break;
case 'P':
txt[i] = '9';
break;
case 'O':
txt[i] = 'A';
break;
case 'R':
txt[i] = 'B';
break;
case 'N':
txt[i] = 'C';
break;
case 'L':
txt[i] = 'D';
break;
case 'K':
txt[i] = 'E';
break;
case 'T':
txt[i] = 'F';
break;
}
}
for (z = 0; z < 230; z++) /*数组倒序 */
{
a[z] = txt[i - 3];
i--;
}
for (z = 8; z < 230; z++) /*解码处理 */
{
if (a[z] < 65)
al = a[z] - 48;
else
al = a[z] - 55;
if ((z % 2) == 1)
{
m[d] = (ah * 16 + al);
d++;
}
ah = al;
}
for (i = 0; i < n; i++) /*提取有效地址 */
{
if (m[i] == '|')
{
m[i] = NULL;
break;
}
else
lg = i;
continue;
}
ab = m;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!