4

304号测试--sub_E90函数分析

 2 years ago
source link: https://sumsunsuns.github.io/2020/04/08/304(5)/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
304号测试--sub_E90函数分析 - PsgQ Blog
File failed to load: http://cdn.mathjax.org/mathjax/latest/extensions/MathMenu.js

最近在忙毕设与复试的内容,304测试暂时没顾上,今天分析了一下sub_E90函数,此函数内容还是挺多的。


1.(_DWORD )?

(_DWORD )是强制类型转化,然后在提领指针。

dword是指注册表的键值,每个word为2个字节,dword双字即为4个字节。

结合以上信息可以推出其中一个代码*(_DWORD *)a1 + 11)的理解应为:

从 a1[11] 开始,按DWORD格式取出 四个字节。

2.byte类型

 byte,即字节,由8位的二进制组成,byte类型的数据是8位带符号的二进制数。

byte类型与int类型的区别?

1、类型不一样,byte是字节数据的类型,int是整型数据的类型。

2、占用的字节不一样,byte占用1 个字节,int占用4个字节。

3、大小范围不一样,byte 的大小范围是道-128—127 ,int的大小范围是-2147483648到2147483647。

3.exit(0),_exit(0),exit(1),exit(-1)作用与区别

exit(0):正常运行程序并退出程序。

_exit(0):不能输出结果,未清除I/O缓存,不打印。

exit(1):非正常运行导致退出程序;

 exit(-1):非正常运行导致退出程序,与1类似。

 在main中return v;的效果与exit(v);相同。

伪代码分析


  __int64 __fastcall sub_E90(__int64 *a1)
{
  __int64 *v1; // rbx
  unsigned int v2; // er14
  __int64 v4; // rsi
  unsigned __int64 v5; // rcx
  __int64 v6; // rdx
  _BYTE *v7; // r15
  __int16 v8; // di
  unsigned __int16 v9; // ax
  __int16 v10; // ax
  __int16 v11; // cx
  __int16 v12; // ax
  __int64 v13; // rax
  __int16 v14; // ax
  __int64 v15; // rax
  __int16 v16; // ax
  unsigned __int16 v17; // ax
  __int16 v18; // dx
  unsigned __int16 v19; // ax
  int v20; // eax
  int v21; // ecx
  int v22; // eax
  __int64 v23; // rax

  v1 = a1;                                 //v1指向数组a1
  v2 = 1;
  if ( !*((_DWORD *)a1 + 11) )             //a1[11]为0
  {
    v4 = *a1;                              //v4等于a1[0]
    v5 = a1[1];                            //v5等于a1[1]
    v6 = *((unsigned __int16 *)a1 + 15);   //v6等于a1[15]
    v7 = (_BYTE *)(*a1 + v6);              //v7等于a1[0]+v6,byte型
    if ( (unsigned __int64)v7 >= v5 )      //v7大于v5
LABEL_72:
      exit(-1);                            //非正常运行退出程序
    v8 = v6 + 4;                           
    *((_WORD *)v1 + 15) = v6 + 4;           //v1[15]=v6+4
    v2 = 0;
    switch ( *v7 + 112 )                    //v7+112
    {
      case 0:
        return v2;                          //返回v2
      case 128:
        v11 = *((_WORD *)v1 + (unsigned __int8)v7[2] + 8) + *((_WORD *)v1 + (unsigned __int8)v7[3] + 8); //v11=a1[v7[2]+8]+a1[v7[3]+8]
        goto LABEL_25;                      //执行LABEL_25之后的代码 

      。。。
      。。。
      。。。



}
return v2;
}

sub_E90完成的是将读取的字节码翻译执行。

把这些字节码送入指令执行引擎函数sub_E90中,将字节码指令从虚拟地址0处开始逐条执行,当遇到HALT指令或发生错误时停止。

myvm中sub_E90函数执行的是中间switch那段,用于识别各种机器指令,并执行。

机器指令按照操作数的不同来分,包括双操作数指令(OP DEST,SRC)、单操作数指令(OPDEST)、无操作数指令(op)等3种。由于操作数的不同直接关系到指令指针IP的变化不同,因此R[IP]值的变化将因具体指令的操作数不同而异。

所以switch中的各个case,是各条指令,比如jmp,jz,sub等

具体功能后续再分析。


参考链接:

详解java中的byte类型



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK