适合新手的虚拟机逆向----2019UNCTF easyvm

看题目知道这是一个虚拟机逆向题目,运行一下知道这是匹配字符串之后用IDA64进行分析,主函数的逻辑还是比较清楚的。先给s上的96字节置0,再给v3分配40字节空间。调用sub_400C1E初始化v3上的内容。用s接收32字符,如果不是32长度就失败,如果是,则调用 **v3函数指针所对应的函数,参数分别是v3, &unk_602080, &unk_6020A0, &s,最后的!=0可以猜测这个函数返回值是逻辑型。这里的V3是一个函数指针,接着分析比较重要的初始化v3的函数sub_400C1E,注意到有个特别的地方:*(_QWORD *)a1 = off_4010A8
之后查看off_4010A8的内容,发现都是一些函数的偏移量。所以这里也可以知道**v3调用的就是sub_400806这个函数接着就开始分析sub_400806这个函数(根据理解稍作改动)这个时候再看一下constvalue和checkcode

接下来重新分析sub_400806函数,函数首先将offset+8被赋值0xa9对应的地址这样就可以看switch中值为0xA9的内容,发现执行offset+80函数指针对应的函数,参数为offset,之后(offset+8)-6,也就是下一个循环将执行0xA3的内容。这里就相当于执行一条命令之后,某个位置的值减去一个值。有点像IP,结合其他case也可以做出这个大胆的假设----offset+8相当于IP
接下来分析offset+80对应的函数,这里可以知道*(_BYTE *)(a1 + 16)=*(_BYTE *)(input+*(unsigned __int8 *)(a1 + 18))接着执行0xA3处的代码

同样可以得到sub_400CD6的代码依次类推。可以按照这个规则先推到处程序执行switch的顺序0xA9u 0xA3u 0xA5u 0xA6u 0xA4u 0xABu 0xA7u 0xAEu 0xA2u 0xADu 0xAFu同理也可以写出其执行的代码过程A9(){    *(_BYTE *)(a1 + 16)=*(_BYTE *)(input + *(unsigned __int8 *)(a1 + 18))} A3(){     *(_BYTE *)(a1 + 16) -= *(_BYTE *)(a1 + 18)} A5(){    *(_BYTE *)(a1 + 17) ^= *(_BYTE *)(a1 + 16)} A6(){    *(_BYTE *)(a1 + 16) = 0xCD} A4(){    *(_BYTE *)(a1 + 16) ^= *(_BYTE *)(a1 + 17)} AB(){    if ( *(_BYTE *)(a1 + 16) == *(_BYTE *)(*(_QWORD *)(a1 + 24) + *(unsigned __int8 *)(a1 + 18)) )        *(_DWORD *)(a1 + 20) = 0    else if ( *(_BYTE *)(a1 + 16) >= *(_BYTE *)(*(_QWORD *)(a1 + 24) + *(unsigned __int8 *)(a1 + 18)) )        *(_DWORD *)(a1 + 20) = 1    else        *(_DWORD *)(a1 + 20) = -1}    A7(){    ++*(_BYTE *)(a1 + 16)} AE(){    if ( *(_DWORD *)(a1 + 20) )        return 0    else        goto A2()} A2(){    ++*(_BYTE *)(a1 + 18)} AD(){    if ( *(_BYTE *)(a1 + 18) > 0x1Fu )         *(_DWORD *)(a1 + 20) = 1    else        *(_DWORD *)(a1 + 20) = 0} AF(){    if ( *(_DWORD *)(a1 + 20) != 1 )        goto A9()    else        return 1}

THE END
喜欢就支持以下吧
点赞0
分享
评论 抢沙发
  • 管埋员

    昵称

  • 取消
    昵称