Sub_CE0分析

Hello world,hello blog!

Posted by 吴柚 on May 8, 2019

首先使用IDA_PRO打开myvm,然后继续打开Sub_CE0函数,按下F5获取C语言伪代码。

FILE *v1; // rax
FILE *v2; // rbx
__int64 v3; // r15
void *v4; // r14
char *v5; // rbx

上述代码定义V1,V2文件变量;V3是64位整型变量;V4是空的动态数组;V5是字符型指针变量。

v1 = fopen(a1, "rb");
v2 = v1;

上述代码含义是打开a1文件,然后操作方式为读取,V2=V1,这段代码不太明白,猜测是V1来打开文件,V2来进行后续操作,以防止出现某种错误。

if ( !v1 )
  return 0LL;
fseek(v1, 0LL, 2);
v3 = ftell(v2);
fseek(v2, 0LL, 0);
v4 = malloc(0x10000uLL);
memset(v4, 0, 0x10000uLL);
fread(v4, 1uLL, v3, v2);
fclose(v2);

上述代码的含义是如果V1不存在或空,则返回0LL;当V1不空时,则进行下述操作:

fseek()函数的作用是把指针放到V1文件末尾偏移量为0LL的位置;

ftell()函数返回的是文件相对于文件首的位置的偏移量;即V3等于V2文件的大小;

把指针放到V2文件首的位置;

malloc()的作用是分配空间,空间的大小为0x10000uLL;

memset(v4,0,0x10000uLL) 把V4动态数组大小为0x10000uLL空间的所有数赋为0,即V4所有内容全为0;

fread(v4, 1uLL, v3, v2) 将V2的1uLL空间的数赋给V4,赋V3次;

close(v2) 将V2文件关闭;

  _mm_storeu_si128(
    (__m128i *)&unk_202018 + 4096,
    _mm_unpacklo_epi64((__m128i)(unsigned __int64)&unk_202018, (__m128i)((unsigned __int64)&unk_202018 + 0x8000)));
  memcpy(y, v4, 0x10000uLL);
  _mm_storeu_si128((__m128i *)&unk_202018 + 4097, (__m128i)0LL);
  *(_QWORD *)((char *)&unk_202018 + 65566) = 0LL;
  *((_WORD *)&unk_202018 + 32785) = 32764;
  *((_QWORD *)&unk_202018 + 8197) = 0LL;
  v5 = (char *)&unk_202018 + 0x10000;
  free(v4);
  return v5;

上述代码的意思为:

_mm_storeu_si128(__m128i *a,__m128i b) 函数的意思为将b赋值给a;

_mm_unpacklo_epi64(__m128i a,__m128i b) 低64位交错,返回的是一个128位的数据。

则上述_mm_storeu_si128()内的内容意思为:&unk_202018地址的低64位和&unk_202018 + 0x8000的低64位交错,然后赋值为)&unk_202018地址向下移动4096位;

` memcpy(&unk_202018, v4, 0x10000uLL) 将V4内所有内容拷贝到原&unk_202018`地址中去;

_mm_storeu_si128((__m128i *)&unk_202018 + 4097, (__m128i)0LL) 将0LL赋值给&unk_202018向下移动4097位地址中去;猜想进过上述几轮操作,只剩下&unk_202018向下移动的第4096位才有数据,其余127位都为0;

_QWORD *是1bit变量的数据类型;

_WORD *是1个字变量的数据类型;

*(_QWORD *)((char *)&unk_202018 + 65566) = 0LL 将0LL赋值到&unk_202018向下移动65566位的地址中;

` *((_WORD *)&unk_202018 + 32785) = 32764 将32764赋值到&unk_202018`向下移动32785位的地址中中;

*((_QWORD *)&unk_202018 + 8197) = 0LL 将0LL赋值到&unk_202018向下移动8197位的地址中;

v5 = (char *)&unk_202018 + 0x10000&unk_202018向下移动0x10000地址中的数转化为字符指针类型然后赋值给V5;

free(v4) 释放V4的地址空间;

return v5 返回V5的值;

总结

此函数的意思为,将a1的文件打开进行一系列操作,然后返回某个地址的值,所以要得到指令,需要对这个地址进行分析,使用的工具应为Linux内的gdb。