«

»

21

[迅雷XV转换器] XVE7s简单分析

等了很久的《轩辕剑》,近期终于开播了(有同追的大牛么= =)~在网上找了找,貌似只有迅雷那里有比较高清的版本(转录的TV版720P),但下载回来发现格式是.xv而非常见的视频格式,迅雷为了“垄断片 源”,自创.xv视频格式,只能由迅雷看看播放器播放,对于我这种伪完美主义者~当然不肯轻易就范了

 

于是在网上找迅雷XV格式转换器,搜了一下发现还真有这东西,很简单的一个小程序,目前的最新版叫XVE7s,作者是“伪红学家”,地址:http://tiancaihb.ixiezi.com/2012/06/19/xve7/

 

这个版本的XVE还新加了个“一秒转换”功能,听起来很强大,下载试了下,很有效,的确是秒速把.xv转换成了.flv。当然了,速度这么快是直接对原始xv文件覆盖写入的(不然光copy一份就要好久呢)。

 

感觉这个小程序很神奇,也很简洁,习惯性拖IDA看了下,没多少sub,刨去MFC框架估计核心代码不会很多(真的很少- -!!),于是就动手分析了一下~

 

暂时只逆了1秒转换部分,支持flv,普通模式还没看。

.text:004015A8                 mov     eax, [esp+11B8h+bIsFastConv]
.text:004015AF                 mov     ebp, ds:fgetc
.text:004015B5                 test    eax, eax
.text:004015B7                 jz      loc_4017D0      ; 是否使用1秒转换
.text:004015BD                 mov     eax, [esp+11B8h+szSourceFile]
.text:004015C4                 push    offset Mode     ; "rb+"
.text:004015C9                 push    eax             ; Filename
.text:004015CA                 call    ds:fopen        ; 打开.xv文件
.text:004015D0                 mov     esi, eax
.text:004015D2                 push    0               ; Origin
.text:004015D4                 push    200000h         ; Offset
.text:004015D9                 push    esi             ; File
.text:004015DA                 call    ds:fseek
.text:004015E0                 add     esp, 14h
.text:004015E3                 lea     edi, [esp+11B8h+buffer]
.text:004015EA                 mov     ebx, 400h
.text:004015EF
.text:004015EF loc_4015EF:                             ; CODE XREF: convert_file+DBj
.text:004015EF                 push    esi             ; File
.text:004015F0                 call    ebp ; fgetc
.text:004015F2                 mov     [edi], eax
.text:004015F4                 add     esp, 4          ; 从0x200000偏移处读取1024字节到DWORD buffer[0x400]
.text:004015F7                 add     edi, 4
.text:004015FA                 dec     ebx
.text:004015FB                 jnz     short loc_4015EF
.text:004015FD                 mov     eax, [esp+11B8h+tOff1]
.text:00401604                 mov     ebx, 4Ch
.text:00401609                 sub     ebx, eax
.text:0040160B                 and     ebx, 0FFh       ; flag = 0x4C – (char)buffer[1]
.text:00401611                 add     eax, ebx
.text:00401613                 cmp     al, 4Ch
.text:00401615                 jnz     loc_4017C2      ; if ((flag + buffer[1]) == 0x4C)
.text:00401615                                         ; 其实这句可以省略,代入flag展开后就是
.text:00401615                                         ; (0x4C – buffer[1] + buffer[1]) == 0x4C
.text:0040161B                 mov     ecx, [esp+11B8h+tOff2]
.text:00401622                 add     ecx, ebx
.text:00401624                 cmp     cl, 56h
.text:00401627                 jnz     loc_4017C2      ; if ((flag + buffer[2]) == 0x56)
.text:00401627                                         ; 对文件格式的检查
.text:0040162D                 mov     edx, [esp+11B8h+szSourceFile]
.text:00401634                 lea     eax, [esp+11B8h+Dest]
.text:00401638                 push    edx
.text:00401639                 push    offset asc_4042F8 ; "
.text:0040163E                 push    eax             ; Dest
.text:0040163F                 call    ds:sprintf
.text:00401645                 mov     edi, [esp+11C4h+unknown_ecx_para]
.text:00401649                 add     esp, 0Ch
.text:0040164C                 lea     ecx, [esp+11B8h+Dest]
.text:00401650                 push    ecx
.text:00401651                 mov     ecx, edi
.text:00401653                 call    list_print_text ; 输出目标文件名(源文件名.flv)
.text:00401653                                         ; 以及各种信息
.text:00401658                 push    offset unk_4042EC
.text:0040165D                 mov     ecx, edi
.text:0040165F                 call    list_print_text
.text:00401664                 push    offset unk_4042D8
.text:00401669                 mov     ecx, edi
.text:0040166B                 call    list_print_text
.text:00401670                 push    0               ; 开始解码
.text:00401672                 push    200000h         ; Offset
.text:00401677                 push    esi             ; File
.text:00401678                 call    ds:fseek
.text:0040167E                 mov     edi, ds:fputc
.text:00401684                 push    esi             ; File
.text:00401685                 push    46h             ; Ch
.text:00401687                 call    edi ; fputc
.text:00401689                 add     esp, 14h
.text:0040168C                 lea     ebp, [esp+11B8h+tOff1] ;
.text:0040168C                                         ; for (i = 0; i < 3; i++) {
.text:0040168C                                         ;     data = (char)buffer[1 + i] + flag;
.text:0040168C                                         ;     fputc(data, fp);
.text:0040168C                                         ; }
.text:00401693                 mov     [esp+11B8h+progress], 3
.text:0040169B
.text:0040169B loc_40169B:                             ; CODE XREF: convert_file+199j
.text:0040169B                 mov     edx, [ebp+0]
.text:0040169E                 push    esi             ; File
.text:0040169F                 add     edx, ebx
.text:004016A1                 and     edx, 0FFh
.text:004016A7                 push    edx             ; Ch
.text:004016A8                 call    edi ; fputc
.text:004016AA                 mov     eax, [esp+11C0h+progress]
.text:004016AE                 add     esp, 8
.text:004016B1                 add     ebp, 4
.text:004016B4                 dec     eax
.text:004016B5                 mov     [esp+11B8h+progress], eax
.text:004016B9                 jnz     short loc_40169B ;
.text:004016B9                                         ; for (i = 0; i < 0x3FC; i++) {
.text:004016B9                                         ;     data = (char)buffer[4 + i] + flag;
.text:004016B9                                         ;     fputc(data, fp);
.text:004016B9                                         ; }
.text:004016BB                 lea     ebp, [esp+11B8h+tOff4]
.text:004016C2                 mov     [esp+11B8h+progress], 3FCh
.text:004016CA
.text:004016CA loc_4016CA:                             ; CODE XREF: convert_file+1C7j
.text:004016CA                 mov     eax, [ebp+0]
.text:004016CD                 push    esi             ; File
.text:004016CE                 add     eax, ebx
.text:004016D0                 and     eax, 0FFh
.text:004016D5                 push    eax             ; Ch
.text:004016D6                 call    edi ; fputc
.text:004016D8                 mov     eax, [esp+11C0h+progress]
.text:004016DC                 add     esp, 8
.text:004016DF                 add     ebp, 4
.text:004016E2                 dec     eax
.text:004016E3                 mov     [esp+11B8h+progress], eax
.text:004016E7                 jnz     short loc_4016CA
.text:004016E9                 mov     ebx, ds:fseek
.text:004016EF                 push    0               ; Origin
.text:004016F1                 push    20000Ah         ; Offset
.text:004016F6                 push    esi             ; File
.text:004016F7                 call    ebx ; fseek
.text:004016F9                 push    esi             ; File
.text:004016FA                 push    20h             ; Ch
.text:004016FC                 call    edi ; fputc     ;
.text:004016FC                                         ; 修正文件头
.text:004016FE                 push    0               ; Origin
.text:00401700                 push    0               ; Offset
.text:00401702                 push    esi             ; File
.text:00401703                 call    ebx ; fseek
.text:00401705                 push    esi             ; File
.text:00401706                 push    46h             ; Ch
.text:00401708                 call    edi ; fputc
.text:0040170A                 push    esi             ; File
.text:0040170B                 push    4Ch             ; Ch
.text:0040170D                 call    edi ; fputc
.text:0040170F                 push    esi             ; File
.text:00401710                 push    56h             ; Ch
.text:00401712                 call    edi ; fputc
.text:00401714                 push    esi             ; File
.text:00401715                 push    1               ; Ch
.text:00401717                 call    edi ; fputc
.text:00401719                 add     esp, 40h
.text:0040171C                 push    esi             ; File
.text:0040171D                 push    5               ; Ch
.text:0040171F                 call    edi ; fputc
.text:00401721                 push    esi             ; File
.text:00401722                 push    0               ; Ch
.text:00401724                 call    edi ; fputc
.text:00401726                 push    esi             ; File
.text:00401727                 push    0               ; Ch
.text:00401729                 call    edi ; fputc
.text:0040172B                 push    esi             ; File
.text:0040172C                 push    0               ; Ch
.text:0040172E                 call    edi ; fputc
.text:00401730                 push    esi             ; File
.text:00401731                 push    9               ; Ch
.text:00401733                 call    edi ; fputc
.text:00401735                 push    esi             ; File
.text:00401736                 push    0               ; Ch
.text:00401738                 call    edi ; fputc
.text:0040173A                 push    esi             ; File
.text:0040173B                 push    0               ; Ch
.text:0040173D                 call    edi ; fputc
.text:0040173F                 push    esi             ; File
.text:00401740                 push    0               ; Ch
.text:00401742                 call    edi ; fputc
.text:00401744                 add     esp, 40h
.text:00401747                 push    esi             ; File
.text:00401748                 push    0               ; Ch
.text:0040174A                 call    edi ; fputc
.text:0040174C                 push    esi             ; File
.text:0040174D                 push    0FFh            ; Ch
.text:00401752                 call    edi ; fputc
.text:00401754                 push    esi             ; File
.text:00401755                 push    1Fh             ; Ch
.text:00401757                 call    edi ; fputc
.text:00401759                 push    esi             ; File
.text:0040175A                 push    0FFh            ; Ch
.text:0040175F                 call    edi ; fputc
.text:00401761                 push    esi             ; File
.text:00401762                 push    0F1h            ; Ch
.text:00401767                 call    edi ; fputc
.text:00401769                 push    esi             ; File
.text:0040176A                 call    ds:fclose
.text:00401770                 mov     esi, [esp+11E4h+szSourceFile]
.text:00401777                 lea     ecx, [esp+11E4h+NewFilename]
.text:0040177E                 push    esi
.text:0040177F                 push    offset aS_flv   ; "%s.flv"
.text:00401784                 push    ecx             ; Dest
.text:00401785                 call    ds:sprintf
.text:0040178B                 lea     edx, [esp+11F0h+NewFilename]
.text:00401792                 push    edx             ; NewFilename
.text:00401793                 push    esi             ; OldFilename
.text:00401794                 call    ds:rename       ; 重命名.xv文件为.flv
.text:0040179A                 add     esp, 40h
.text:0040179D                 test    eax, eax
.text:0040179F                 jz      short loc_4017AF
.text:004017A1                 mov     ecx, [esp+11B8h+unknown_ecx_para]
.text:004017A5                 push    offset unk_404298
.text:004017AA                 call    list_print_text
.text:004017AF
.text:004017AF loc_4017AF:                             ; CODE XREF: convert_file+27Fj
.text:004017AF                 mov     ecx, [esp+11B8h+unknown_ecx_para]
.text:004017B3                 push    offset aK       ; "转换完成\r\n"
.text:004017B8                 call    list_print_text

然后人工翻译了成C码,调试了一下,可以成功将.xv转换成.flv(xv文件须合法,反正够我看轩辕剑的了= =)

#include <stdio.h>
#include <stdlib.h>

 

int convert_file(char *szSourceFile, int bIsFastConv)
{
    char szNewFileName[256] = {0};

    int buffer[0x400];
    int i;
    char flag;
    char data;

    if (bIsFastConv) {   // 一秒转换模式
        FILE *fp = fopen(szSourceFile, "rb+");
        if (!fp) {
            printf("未找到文件.\n\n");
            return 0;
        }

        fseek(fp, 0x200000, 0);
        for (i = 0; i < 0x400; i++) {
            buffer[i] = fgetc(fp);
        }

        flag = 0x4C – (char)buffer[1];
        if (flag + (char)buffer[2] == 0x56) {
            // 开始解码
            fseek(fp, 0x200000, 0);
            fputc(0x46, fp);
            
            for (i = 0; i < 3; i++) {
                data = (char)buffer[1 + i] + flag;
                fputc(data, fp);
            }

            for (i = 0; i < 0x3FC; i++) {
                data = (char)buffer[4 + i] + flag;
                fputc(data, fp);
            }

            fseek(fp, 0x20000A, 0);
            fputc(32, fp);

            // 修正文件头
            fseek(fp, 0, 0);
            fputc(70, fp);
            fputc(76, fp);
            fputc(86, fp);
            fputc(1, fp);
            fputc(5, fp);
            fputc(0, fp);
            fputc(0, fp);
            fputc(0, fp);
            fputc(9, fp);
            fputc(0, fp);
            fputc(0, fp);
            fputc(0, fp);
            fputc(0, fp);
            fputc(255, fp);
            fputc(31, fp);
            fputc(255, fp);
            fputc(241, fp);

            fclose(fp);

            sprintf(&szNewFileName[0], "%s.flv", szSourceFile);
            rename(szSourceFile, &szNewFileName[0]);

            printf("转换完成.\n输出文件: %s\n\n", szNewFileName);
        } else {
            printf("文件格式不正确.\n\n");
            return 0;
        }
    } /*else {   // 常规模式(未完成)

    }*/
    return 1;
}

int main(int argc, char **argv)
{
    char szFileName[256] = {0};
    printf("迅雷XV格式转换器 XVE7s 秒速转换逆向版本\n   Code by Naylon\n   http://hi.baidu.com/naylonslain");
    if (argc > 1) {
        convert_file(argv[1], 1);
    } else {
        // Test Input: "D:\Downloads\000.xv"
        while (1) {
            scanf("%s", &szFileName[0]);
            convert_file(szFileName, 1);
            memset(&szFileName[0], 0, 256);
        }
    }
    return 0;
}

本文仅作学习研究

5 comments

Skip to comment form

  1. Sh1n0b1

    I had some trouble compiling the code at first, but I resolved. One proble I couldn't fix was this line as causing some problem so I commented it out. " if (flag + (char)buffer[2] == 0×56) {" .

    Thanks for the code, I couldn't download this from 115 because I couldn't register for an account since I don't have an active cell phone number :( 

    Awesome post. 

     

    [回复]

    Naylon 回复:

    Thx for ur comment.

    But i'm confused since i have no trouble compiling the code using VC6. And idk what's wrong with "if (flag + (char)buffer[2] == 0×56) {". Did i make a mistake? Forgiving my bad coding style :(

    115 is easy to register, maybe i can help u if u met some troubles.

    btw…you're not Chinese, are you? How did u know my blog? XD

    [回复]

    Sh1n0b1 回复:

    Yeah, I am chinese. I didn't have any problem compiling that line, but that boolean statement keep return false when I try to convert the xv files so i just comment it out. 

    I found your blog when I was search for another link to download the XVE7s.

    By the way, where did you learn your IDA pro skill from? 

    [回复]

  2. 学习英文来的

    学习英文来的。。太霸道了。

    [回复]

  3. Leland

    well,thank you for your nice project,you have done something I intended for long but never get down to.the xv converter is a good work which is said to be developed by a now CMU student when he was at high school some a decade ago,and xv converter project is now open source sine 2013.

    [回复]

发表评论

电子邮件地址不会被公开。 必填项已用*标注

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>