通过逆向学习软件设计(3)

    新的一年来到了,这个系列的文章也由于各种原因拖了好久,无奈地也跟着跨年了!接下来几篇重点在于URL数据文件data.dat的定位及解密过程。根据上一篇的内容,我们很容易了解到大致的定位方法及方式,现在我们就要首先从逆向源码的角度来验证一下通过API调用流程监控结果的猜想。

    首先,对于文件的各种操作着手,很容易进行API断点,然后通过栈回溯的方法定位到相关的关键代码位置,这个过程相对简单,省略不表(欢迎有兴趣且不是很懂的童鞋来问);

    然后,分析出通过电台索引获取密文的函数(如图1,已经加好了标签及相关注释),并逆向源码如下:


int getIDPFilePosIdx( int iIdx )
{
    std::ifstream objFile( "data.idi" );
    objFile.seekg( 0, std::ios::end );

    int iPos = (int)objFile.tellg();
    if ( -1 == iPos )
        return -1;

    iPos = iPos/8 - 1;
    int iSeek   = 0;
    int iGet    = 0;
    if ( iPos >= 0 )
    {
        int iData(0);
        do 
        {
            iGet = (iPos+iSeek)/2;
            objFile.seekg( iGet*8 );
            objFile.read( (char*)&iData, 4 );
            if ( iIdx == iData )
            {
                objFile.read( (char*)&iData, 4 );
                objFile.close();
                return iData;
            }
            if ( iIdx > iData)
                iSeek = iGet+1;
            else
                iPos = iGet-1;

        } while ( iPos >= iSeek );
    }

    objFile.close();
    return -1;
}

int GetIDP_Data( int iIdx )
{
    if ( iIdx > 0 )
    {
        std::ifstream objFile("data.idp");
        objFile.seekg( 0, std::ios::end );
        int iSize = (int)objFile.tellg();
        objFile.seekg( 4*(iIdx-1) );
        if ( objFile.tellg() < (iSize-8) )
        {
            int iData(0);
            objFile.read( (char*)&iData, 4 );
            objFile.close();
            return iData;
        }
    }

    return -1;
}

char* getDATFileData( int iIdx, int &ibuflen )
{
    int iData = GetIDP_Data( iIdx );
    if ( iData >= 0 )
    {
        int iDataGet = GetIDP_Data( iIdx+1 );
        std::ifstream objFile("data.dat");
        objFile.seekg( iData );
        int uStrLen = iDataGet - iData -2;
        char *pBuf = new char[uStrLen];
        objFile.read( pBuf, uStrLen );
        //get length
        ibuflen = uStrLen;
        objFile.close();
        return pBuf;
    }

    return NULL;
}

运行测试结果与动态调试一致,还原结果一致:


      通过对数据定位过程的分析,发现与API流程分析的结果大致相同,都是采用折半法通过电台ID进行索引定位获取位置信息,然后通过位置信息,获取对应的data.dat中的相应加密后的待解密的URLs信息。

     接下来,获取了276字节长度的密文后(测试程序中VOA电台的密文),就要开始着手进行解密操作了,避开一些对文件进行格式检查完整性检查的一些函数,直接定位到关键核心的解密相关函数,如下图2,这个函数不算短,里面还还有不少功能函数在其中,工作量不算小啊~~


通过OD跟踪至核心函数,如下:


解密前,首先检查初始的Key是否满足要求,回退指针4个字节,检查长度是否为8个,不够8个字节则补零处理:



当进行完Key的检查及拷贝工作后,就要对Key进行处理了,接下来的函数我命名为Key的准备函数


    在分析密钥准备函数之前,先看一下定位到的解密核心函数,弄清楚到底这个Key是肿么用的,另外是怎么传过去的,还有哪些内置的Keys等等,那么首先,进入解密的核心函数——DecodeEncryptDataPartly_8Bytes,这个函数比较有意思,每次解密8个字节,循环内完成所有加密数据的解密工作。


    这个8字节解密核心函数,是整个解密过程中的关键所在,也汇聚了所有相关数据及Key的要素,包括一些内置的参与运算的数据,比如说“Shagua”,作者取名的这个数据估计也是为了娱乐一下吧~:D,我们把Key准备函数放到一边,重点研究一下这个核心且关键的8字节解密函数,当然一如既往地,这个函数里面的子函数也是不少的,另外关键的那个点就是传处理后的密钥的那个,这里就不留悬念了,是通过全局(静态)变量进行的传参操作,如图:


很明显在静态状态下这个数据段里面的数据时没有初始化的,当进行动态跟踪后,很容易在PrepareKey函数执行完后,发现这个区域已经被赋值了。【应该是6个字节,图例说明数字有出入】


接下来,就针对核心的解密函数及其子函数小伙伴们进行逆向,并验证效果,先不要急,鉴于子函数较多,因此挨个挨个来,首先把他们分解一下,在DecodeEncryptDataPartly_8Bytes函数中,含三个子函数sub_525444,sub_52594C,sub_5254C4,其中sub_52594C 中又含有sub_525544、sub_525654、sub_5255D4三个子函数,一共加起来,我们需要分析还原大约六个函数,为了不让这篇文章过长看着累,在这里就割一下,在第四篇里面写六个小函数的逆向还原。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值