Vape (Vape Ghost Client) 是一个 Minecraft 作弊客户端。Vape 客户端允许玩家在 Minecraft 中使用一些自动化功能或作弊工具,如自动瞄准、飞行、透视等。该客户端使用特殊的加载方式(动态注入)在 Windows 平台下比较受欢迎,本文章通过逆向工程,分析VapeV4与VapeLite,阐述该客户端的工作原理。

注:本程序分析截至 2025/07/15,不保证后续更新版本是否会对核心功能进行修改。

分析 VapeV4

主程序

一般情况下,主程序是从官网下载的,名字是 f"{random_hex_str}.exe" ,部分代码使用CodeVirtualizer进行代码虚拟化。

main函数

main函数仅输出1,而后进入after_main

我们认为 after_main 函数也是main函数的一部分。

申请 SeDebugPrivilege 权限

因为主程序要使用 OpenProcess API操作其他程序,且要执行远程线程注入,申请此权限是必须的。

socket 监听本地地址

bind_localhost函数监听本地地址(127.0.0.1),用于和注入的客户端进行通信。

RenderingUI

RenderingUI启用了两个线程,并且有一个循环负责同步。

第一个线程用于渲染Login界面,第二个线程用于与第一个线程配合,完成App-Auth流程。

在UI渲染完毕后,该函数返回。

Vape客户端的UI渲染通过一个循环实现,使用了大量的OpenGL API,笔者对于GL不熟悉,技术细节在此不表。

不过显而易见的,各种界面的切换是通过一个全局变量决定的。

检测 Minecraft 存活

通过进程名检测

_BOOL8 __fastcall checkValidMinecraftProcess(PROCESSENTRY32W *a1)
{
  return wcsstr(a1->szExeFile, L"javaw.exe") || wcsstr(a1->szExeFile, L"java.exe") || wcsstr(a1->szExeFile, L"Paladium");
}
bool __fastcall locateProcess(_QWORD *a1)
{
  CHAR *v2; // rax
  signed __int64 v3; // rcx
  unsigned __int8 v4; // dl
  int v5; // eax
  unsigned __int8 *ProcessParameters; // [rsp+20h] [rbp-788h]
  HWND hWnd; // [rsp+30h] [rbp-778h]
  HANDLE hSnapshot; // [rsp+40h] [rbp-768h]
  PROCESSENTRY32W pe; // [rsp+50h] [rbp-758h] BYREF
  CHAR ClassName[256]; // [rsp+290h] [rbp-518h] BYREF
  CHAR String[1024]; // [rsp+390h] [rbp-418h] BYREF

  hSnapshot = CreateToolhelp32Snapshot(2u, 0);
  pe.dwSize = 568;
  if ( !Process32FirstW(hSnapshot, &pe) )
    return 0;
  do
  {
    if ( checkValidMinecraftProcess(&pe) )
    {
      ProcessParameters = getProcessParameters(pe.th32ProcessID);
      hWnd = (HWND)sub_14004BD10(pe.th32ProcessID);
      if ( hWnd )
      {
        if ( ProcessParameters && _strstr((const char *)ProcessParameters, "MojangTricksIntelDriversForPerformance") )
          goto LABEL_18;
        memset(String, 0, sizeof(String));
        GetWindowTextA(hWnd, String, 1024);
        if ( _strstr(String, "Minecraft 1.")
          || _strstr(String, "????")
          || _strstr(String, "Paladium")
          || _strstr(String, " Client") )
        {
          goto LABEL_18;
        }
        memset(ClassName, 0, sizeof(ClassName));
        GetClassNameA(hWnd, ClassName, 256);
        v2 = ClassName;
        v3 = "LWJGL" - ClassName;
        while ( 1 )
        {
          v4 = *v2;
          if ( *v2 != v2[v3] )
            break;
          ++v2;
          if ( !v4 )
          {
            v5 = 0;
            goto LABEL_17;
          }
        }
        v5 = v4 < (unsigned __int8)v2[v3] ? -1 : 1;
LABEL_17:
        if ( !v5 )
LABEL_18:
          sub_14004C2B0(a1, &pe.th32ProcessID);
      }
      if ( ProcessParameters )
        j_j_free(ProcessParameters);
    }
  }
  while ( Process32NextW(hSnapshot, &pe) );
  return !sub_14001F750(a1);
}

在检测到指定的程序名后,Vape会检测其标题名是否合法,若合法,还会检查窗口类名是否为"LWJGL",进一步提高目标进程的准确性,若未找到Minecraft,Vape会进行循环一直寻找,直到查找到,然后会在GUI上显示,让用户选择。

对于已注入的客户端,Vape会进行检测。

Vape主程序会尝试创建一个pipe,名称后面加上pid,若创建成功,则证明客户端已被注入,若创建失败且上一次的错误是0xE7(ERROR_PIPE_BUSY),说明客户端已被注入,否则证明客户端未被注入。

这也是一种检测Vape客户端的方案,检测工具只需检测此通道的有效性即可证明是否注入Vape客户端。

当然,最简单且有效的方案其实是对java.exe的内存进行全量扫描。

Hwid

Vape 采用硬盘序列号来生成Hwid,在我这里,Hwid是长度为8的hex字符串。

Login

RenderingUI完毕后,after_main函数进入最后面的VM段。该VM段作为程序中第一个VM段,CodeVirtualizer会解密后续所有的字节码,而后进入VM。VM会调用一系列函数。Vape首先检查与服务器的通讯是否正常,若正常,则State=3,而后进入登录检查

下面两个函数均是递归调用自己,而他们的Caller在after_main函数中(被VM了)。

check_Valid_LoginState_VM 大致伪代码

bool check_Valid_LoginState_VM()
{
	char hwid[0x60];
	size_t i;
	DWORD v;
	srand(time(0));
	
	// example hwid: 1234abcd
	getUserHwid(&hwid); 
	
	// Xor Hwid with byte 0x0A, After: ;89>khin
	// 此处VM执行时间很长,效率较低,每次xor都要遍历一遍hwid
	for(i = 0; i < strlen(hwid); i++)
		hwid[i] ^= 0x0A;
	
	log("3\n");
	log(hwid + "\n");
	log("V4");
	
	// 与另一个线程同步,用于HttpRequest
	SetEvent();
	WaitForSingleObject();
	retval = OtherHttpReqFunction();
	
	strstr(retval, "ok");
	v = rand();
	Dword2Hex(v);
	// Lazy To Reverse... That's not important part.
	return true;
}

UserSettings

检查完登录状态后,下来会获取用户设定。UserToken是登陆后服务器返回的值。

// Hidden C++ exception states: #wind=2
__int64 GetUserSettings()
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  user_token = get_user_token();
  sub_140014DB0(v23, "/api/v1/%s/settings/load/global", user_token);
  sub_1400082B0(v14, v23);
  sub_1400082B0(v13, "online.vape.gg");
  sub_140017800(v22, v13, v14);
  sub_1400089E0(v13);
  sub_1400089E0(v14);
  v3 = 0;
  try
  {
    v8 = sub_14001E800(v19, 0LL);
    LOBYTE(v1) = 1;
    sub_140020520(v21, v22, v8, v1, 0);
    sub_1400082B0(v15, "successful");
    v4 = sub_14001E850(v21, v15);
    sub_1400089E0(v15);
    if ( v4 )
    {
      v9 = sub_140020680(v21, "successful");
      if ( sub_1400206C0(v9) )
      {
        sub_1400082B0(v16, "data");
        v5 = sub_14001E850(v21, v16);
        sub_1400089E0(v16);
        if ( v5 )
        {
          v10 = sub_140020680(v21, "data");
          sub_14001E9A0(v20, v10);
          sub_1400082B0(v17, "cache");
          v6 = sub_14001E850(v20, v17);
          sub_1400089E0(v17);
          if ( v6 )
          {
            v11 = sub_140020680(v20, "cache");
            settings_cache = sub_1400206C0(v11);
            v3 = 1;
          }
          sub_1400082B0(v18, "firstRun");
          v7 = sub_14001E850(v20, v18);
          sub_1400089E0(v18);
          if ( v7 )
          {
            v12 = sub_140020680(v20, "firstRun");
            byte_140421A49 = sub_1400206C0(v12);
            v3 = 1;
          }
          sub_14001E8E0(v20);
        }
      }
    }
    sub_14001E8E0(v21);
  }
  catch ( std::exception )
  {
  }
  if ( !v3 )
  {
    settings_cache = 0;
    byte_140421A49 = 0;
  }
  return sub_1400089E0(v22);
}

创建CacheDir(.vapeclient)

创建完Dir后,Vape会检测一次是否发生错误,如果没有错误,进入Inject阶段。

Injection

bool InjectMain()
{
  __int64 v1; // rax
  int v2; // [rsp+20h] [rbp-38h]
  __int64 v3; // [rsp+28h] [rbp-30h]
  _BYTE v4[16]; // [rsp+30h] [rbp-28h] BYREF

  setStage(4u);
  v2 = sub_14000DCA0();
  if ( v2 == 1 )
  {
    setStage(5u);
    LODWORD(v1) = write_process((__int64)v4, hProcess, (void *)listening_port);
    v3 = v1;
    if ( !v1 )
      sub_14009A6D0((__int64)"Failed to inject\n"
                             "Use a supported Minecraft version and client listed on the FAQ of the website");
    return v3 != 0;
  }
  else
  {
    if ( v2 == 8 )
      sub_14009A6D0((__int64)"Couldn't connect to server.\n"
                             "This may caused by an anti-virus or router blocking the connection, or another network issue. 1");
    if ( v2 == 9 )
      sub_14009A6D0((__int64)"Couldn't connect to server.\n"
                             "This may caused by an anti-virus or router blocking the connection, or another network issue. 2");
    if ( v2 == 3 )
      sub_14009A6D0((__int64)"Error connecting");
    if ( v2 == 4 )
      sub_14009A6D0((__int64)"No data read");
    if ( v2 == 5 )
      sub_14009A6D0((__int64)"Error 5");
    if ( v2 == 6 )
      sub_14009A6D0((__int64)"Error 1");
    if ( v2 == 7 )
      sub_14009A6D0((__int64)"Error -1");
    return 0;
  }
}

int __fastcall write_process(__int64 a1, void *a2, void *a3)
{
  return WriteHackedClientToJava(a2, *(void **)a1, *(_DWORD *)(a1 + 8), a3);
}

int __cdecl WriteHackedClientToJava(void *ppExcept, void *pType, int adjectives, void *pBuildObj)
{
  HMODULE ModuleHandleW; // rax
  DWORD v5; // eax
  DWORD v6; // eax
  DWORD v7; // eax
  DWORD LastError; // eax
  int v10; // [rsp+40h] [rbp-48h]
  char *lpBaseAddress; // [rsp+48h] [rbp-40h]
  int v12; // [rsp+50h] [rbp-38h]
  DWORD flOldProtect; // [rsp+64h] [rbp-24h] BYREF
  DWORD ThreadId; // [rsp+68h] [rbp-20h] BYREF

  v12 = 0;
  ThreadId = 0;
  ModuleHandleW = GetModuleHandleW(L"ntdll.dll");
  NtWriteVirtualMemory = (__int64)GetProcAddress(ModuleHandleW, "NtWriteVirtualMemory");
  if ( ppExcept && pType && adjectives )
  {
    v10 = sub_14009B710(pType);
    if ( v10 )
    {
      lpBaseAddress = (char *)VirtualAllocEx(ppExcept, 0LL, (unsigned int)adjectives, 0x3000u, 4u);
      if ( lpBaseAddress )
      {
        if ( WriteProcessMemory(ppExcept, lpBaseAddress, pType, (unsigned int)adjectives, 0LL) )
        {
          flOldProtect = 0;
          if ( VirtualProtectEx(ppExcept, lpBaseAddress, (unsigned int)adjectives, 0x40u, &flOldProtect) )
          {
            return (unsigned int)CreateRemoteThread(
                                   ppExcept,
                                   0LL,
                                   0x100000uLL,
                                   (LPTHREAD_START_ROUTINE)&lpBaseAddress[v10],
                                   pBuildObj,
                                   0,
                                   &ThreadId);
          }
          else
          {
            LastError = GetLastError();
            printf("e4 %i\n", LastError);
          }
        }
        else
        {
          v7 = GetLastError();
          printf("e3 %i\n", v7);
        }
      }
      else
      {
        v6 = GetLastError();
        printf("e2 %i\n", v6);
      }
    }
    else
    {
      v5 = GetLastError();
      printf("e1 %i\n", v5);
    }
  }
  return v12;
}

代码均已贴出,意思不言而喻,通过打开Minecraft进程,随后写入PE文件,然后进行远程线程注入,启动特定的函数,并且传入本地监听的端口号。

其中,sub_14000DCA0函数是VM的,对于这个函数,大概率是下载或者是解密即将注入的PE文件,这不是我们分析的重点。

至此,主程序的大部分功能已经分析完毕,对于Socket通信,我们留在注入的进程中进行讲解。

InjectedStub - 注入的DLL

我们可以从主程序的WriteProcessMemory过程中很容易地Dump出注入的DLL文件,并且从CreateRemoteThread中可以很容易得到即将运行的线程从哪个地址开始。

PE ReflectiveLoader

我们发现DLL导出了一个名为tim的函数,线程也是从这里开始运行的。

void (__fastcall *__fastcall tim(void *a1))(__int64, __int64, void *)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  v44 = 0LL;
  v45 = 0LL;
  v42 = 0LL;
  v46 = 0LL;
  for ( i = sub_180023D10(); ; --i )
  {
    if ( *i == 0x5A4D )
    {
      v35 = *(i + 60);
      if ( v35 >= 0x40 && v35 < 0x400 && *(i + v35) == 17744 )
        break;
    }
  }
  for ( j = NtCurrentPeb()->Ldr->InMemoryOrderModuleList.Flink; j; j = j->Flink )
  {
    Flink = j[5].Flink;
    Blink = j[4].Blink;
    v15 = 0;
    do
    {
      v16 = sub_180023CA0(v15);
      if ( LOBYTE(Flink->Flink) < 0x61u )
        Flink_low = LOBYTE(Flink->Flink);
      else
        Flink_low = LOBYTE(Flink->Flink) - 32;
      v15 = Flink_low + v16;
      Flink = (Flink + 1);
      --Blink;
    }
    while ( Blink );
    if ( v15 == 0x6A4ABC5B )                    // Kernel32_Hash
    {
      v6 = j[2].Flink;
      v32 = (v6 + *(&v6[8].Blink + SHIDWORD(v6[3].Blink)));
      v37 = (v6 + v32[8]);
      v40 = (v6 + v32[9]);
      v4 = 3;
      while ( v4 )
      {
        v31 = sub_180023CB0(v6 + *v37);
        if ( v31 == 0xEC0E4E8E || v31 == 0x7C0DFCAA || v31 == 0x91AFCA54 )
        {
          v39 = (v6 + 4 * *v40 + v32[7]);
          if ( v31 == 0xEC0E4E8E )
          {
            v44 = (v6 + *v39);
          }
          else if ( v31 == 0x7C0DFCAA )
          {
            v45 = (v6 + *v39);
          }
          else
          {
            v42 = (v6 + *v39);
          }
          --v4;
        }
        ++v37;
        ++v40;
      }
    }
    else if ( v15 == 1023043677 )
    {
      v7 = j[2].Flink;
      v33 = (v7 + *(&v7[8].Blink + SHIDWORD(v7[3].Blink)));
      v38 = (v7 + v33[8]);
      v41 = (v7 + v33[9]);
      v5 = 1;
      while ( v5 )
      {
        if ( sub_180023CB0(v7 + *v38) == 1397492408 )
        {
          v46 = (v7 + *(&v7->Flink + 4 * *v41 + v33[7]));
          --v5;
        }
        ++v38;
        ++v41;
      }
    }
    if ( v44 && v45 && v42 && v46 )
      break;
  }
  v36 = *(i + 60) + i;
  v8 = (v42)(0LL, *(v36 + 80), 12288LL, 64LL);
  v10 = *(v36 + 84);
  v25 = i;
  for ( k = v8; v10--; ++k )
    *k = *v25++;
  v11 = (v36 + *(v36 + 20) + 24);
  v43 = *(v36 + 6);
  while ( v43-- )
  {
    v26 = (v11[3] + v8);
    v18 = (v11[5] + i);
    v21 = v11[4];
    while ( v21-- )
      *v26++ = *v18++;
    v11 += 10;
  }
  for ( m = (*(v36 + 144) + v8); m[3]; m += 5 )
  {
    v29 = v44(m[3] + v8);
    v22 = (*m + v8);
    for ( n = (m[4] + v8); *n; ++n )
    {
      if ( v22 && *v22 < 0 )
      {
        v34 = *(*(v29 + 60) + v29 + 136) + v29;
        *n = *(*(v34 + 28) + v29 + 4 * (*v22 - *(v34 + 16))) + v29;
      }
      else
      {
        *n = (v45)(v29, *n + v8 + 2);
      }
      if ( v22 )
        ++v22;
    }
  }
  v30 = v8 - *(v36 + 48);
  if ( *(v36 + 180) )
  {
    for ( ii = (*(v36 + 176) + v8); ii[1]; ii = (ii + ii[1]) )
    {
      v13 = *ii + v8;
      v27 = (ii[1] - 8) / 2;
      for ( jj = ii + 2; v27--; ++jj )
      {
        switch ( HIBYTE(*jj) >> 4 )
        {
          case 10:
            *(v13 + (*jj & 0xFFF)) += v30;
            break;
          case 3:
            *(v13 + (*jj & 0xFFF)) += v30;
            break;
          case 1:
            *(v13 + (*jj & 0xFFF)) += WORD1(v30);
            break;
          case 2:
            *(v13 + (*jj & 0xFFF)) += v30;
            break;
        }
      }
    }
  }
  v14 = (*(v36 + 40) + v8);
  (v46)(-1LL, 0LL, 0LL);
  v14(v8, 1LL, a1);
  return v14;
}

根据分析,我们可以确定这是一个自定义的PE加载器,其代码与 ReflectiveDLLInjection/dll/src/ReflectiveLoader.c at 5198e33b5b2cc6ab70c7bd2439c25a022e90ae1e · rapid7/ReflectiveDLLInjection 非常相似,这对我们分析十分有益。

在加载完后,根据代码分析,它将会调用PE的OEP,对于DLL来说,也就是DllMain。

非常遗憾,DllMain也是加了VM的,我们去虚拟化后继续分析。

JNI_GetCreatedJavaVMs

Vape通过本函数获取当前的JVM。

随后调用其他初始化流程,这里还调用了System.gc(),可能是为了清理一些痕迹。

加载jvm.dll,使用BoyerMooreSearch在Jvm.dll空间内寻找字节序列 99 1E E0,并将其Patch掉,但是本分支在我的电脑上并未执行到,这三个字节暂时不知道有什么用途。

后续发现,这个Get_jvm函数是由VM中调用的,而不是这段代码。

FetchJByteCode

StubDll通过链接本地Socket,发送特定payload,使主程序回应所有的要注入的Java class。所有的class均通过socket传递到客户端,随后,客户端通过DefineClass注册类,通过RegisterNatives注册所有的Native函数。

Dump Classes

通过X64dbg提供的Breakpoint Expression功能,断DefineClass即可。

savedata C:\Users\Administrator\Desktop\vape\dump\\{utf8@rdx}.class, r9, Dword(rsp+0x20); run

RegisterNatives

Vape分几次注册Natives函数,所有注册函数的调用均在VM中完成,所有的注册均在DefineClass完成之后。

第一次注册了主类中的所有重要Native函数

关于RegisterNatives的参数传递,官方解释如下

jint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods);

Registers native methods with the class specified by the clazz argument. The methods parameter specifies an array of JNINativeMethod structures that contain the names, signatures, and function pointers of the native methods. The name and signature fields of the JNINativeMethod structure are pointers to modified UTF-8 strings. The nMethods parameter specifies the number of native methods in the array. The JNINativeMethod structure is defined as follows:

typedef struct {
    char *name;
    char *signature;
    void *fnPtr;
} JNINativeMethod;

The function pointers nominally must have the following signature:

ReturnType (*fnPtr)(JNIEnv *env, jobject objectOrClass, ...);

于是我们可以看懂下面的这些注册

第一批

000000F85A0FF6F0  000002E7813869F0  ði8.ç...  "exit"
000000F85A0FF6F8  000002E781382880  .(8.ç...  "(Z)V"
000000F85A0FF700  000002E780558190  ..U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4470
000000F85A0FF708  000002E7805FD8BC  ¼Ø_.ç...  "dc"
000000F85A0FF710  000002E781365AC0  ÀZ6.ç...  "()V"
000000F85A0FF718  000002E780558200  ..U.ç...  vape.unsigned __int64 __cdecl tim(void *)+44E0
000000F85A0FF720  000002E7805FD8C4  ÄØ_.ç...  "fs"
000000F85A0FF728  000002E78137A1C0  À¡7.ç...  "()V"
000000F85A0FF730  000002E780558230  0.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4510
000000F85A0FF738  000002E7805FD8CC  ÌØ_.ç...  "gc"
000000F85A0FF740  000002E78138B3D0  г8.ç...  "(Ljava/lang/String;)Ljava/lang/Class;"
000000F85A0FF748  000002E780558270  p.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4550
000000F85A0FF750  000002E7805FD8F8  øØ_.ç...  "gt"
000000F85A0FF758  000002E781365430  0T6.ç...  "(Ljava/lang/String;)[B"
000000F85A0FF760  000002E7805582E0  à.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+45C0
000000F85A0FF768  000002E7805FD918  .Ù_.ç...  "gs"
000000F85A0FF770  000002E78138AA90  .ª8.ç...  "()Ljava/lang/String;"
000000F85A0FF778  000002E780558300  ..U.ç...  vape.unsigned __int64 __cdecl tim(void *)+45E0
000000F85A0FF780  000002E7805FD938  8Ù_.ç...  "ss"
000000F85A0FF788  000002E781380210  ..8.ç...  "(Ljava/lang/String;)V"
000000F85A0FF790  000002E780558330  0.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4610
000000F85A0FF798  000002E781380470  p.8.ç...  "ss_2"
000000F85A0FF7A0  000002E7813828B0  °(8.ç...  "(Ljava/lang/String;)I"
000000F85A0FF7A8  000002E7805583C0  À.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+46A0
000000F85A0FF7B0  000002E78135DE30  0Þ5.ç...  "ss_3"
000000F85A0FF7B8  000002E781382270  p"8.ç...  "(Ljava/lang/String;)I"
000000F85A0FF7C0  000002E780558470  p.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4750
000000F85A0FF7C8  000002E78137EF50  Pï7.ç...  "gcj"
000000F85A0FF7D0  000002E78137B6F0  ð¶7.ç...  "(Ljava/lang/String;)Ljava/lang/Class;"
000000F85A0FF7D8  000002E7805585E0  à.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+48C0
000000F85A0FF7E0  000002E78138AB00  .«8.ç...  "gcs"
000000F85A0FF7E8  000002E781389970  p.8.ç...  "(Ljava/lang/Class;)Ljava/lang/String;"
000000F85A0FF7F0  000002E780558670  p.U.ç...  L"襌⑄䠘咉ဤ襈⑌圈腈胬"
000000F85A0FF7F8  000002E7805FD9F8  øÙ_.ç...  "cs"
000000F85A0FF800  000002E781394030  0@9.ç...  "(I)Ljava/lang/String;"
000000F85A0FF808  000002E7805587F0  ð.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4AD0
000000F85A0FF810  000002E7805FDA18  .Ú_.ç...  "rl"
000000F85A0FF818  000002E78133E080  .à3.ç...  "()V"
000000F85A0FF820  000002E7805369C0  ÀiS.ç...  vape.000002E7805369C0
000000F85A0FF828  000002E7805FDA20   Ú_.ç...  "mb"
000000F85A0FF830  000002E78137F310  .ó7.ç...  "(I)V"
000000F85A0FF838  000002E780558590  ..U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4870
000000F85A0FF840  000002E78138C4C0  ÀÄ8.ç...  "grh"
000000F85A0FF848  000002E781380690  ..8.ç...  "()Ljava/lang/Object;"
000000F85A0FF850  000002E780558830  0.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4B10
000000F85A0FF858  000002E78137E9A0   é7.ç...  "cpy"
000000F85A0FF860  000002E781368A60  `.6.ç...  "(Ljava/lang/String;)V"
000000F85A0FF868  000002E780558850  P.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4B30
000000F85A0FF870  000002E781365BA0   [6.ç...  "gks"
000000F85A0FF878  000002E781393A30  0:9.ç...  "(I)S"
000000F85A0FF880  000002E780558A30  0.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4D10
000000F85A0FF888  000002E7805FDA74  tÚ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A9D54
000000F85A0FF890  000002E78137AD30  0.7.ç...  "(Ljava/lang/String;)V"
000000F85A0FF898  000002E7805589D0  Ð.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4CB0
000000F85A0FF8A0  000002E78133D1A0   Ñ3.ç...  "gco"
000000F85A0FF8A8  000002E781394D80  .M9.ç...  "(Ljava/lang/Class;)[Ljava/lang/Object;"
000000F85A0FF8B0  000002E780558AB0  °.U.ç...  L"襌⑄䠘咉ဤ襈⑌圈腈胬"
000000F85A0FF8B8  000002E78137E7C0  Àç7.ç...  "trn"
000000F85A0FF8C0  000002E78135F9F0  ðù5.ç...  "(DDD)[D"
000000F85A0FF8C8  000002E780558CA0   .U.ç...  vape.unsigned __int64 __cdecl tim(void *)+4F80
000000F85A0FF8D0  000002E78138B5E0  àµ8.ç...  "gcb"
000000F85A0FF8D8  000002E78137F3D0  Ðó7.ç...  "(Ljava/lang/Class;)[B"
000000F85A0FF8E0  000002E7805593C0  À.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+56A0
000000F85A0FF8E8  000002E78137A7E0  à§7.ç...  "scb"
000000F85A0FF8F0  000002E781386BB0  °k8.ç...  "(Ljava/lang/Class;[B)I"
000000F85A0FF8F8  000002E780559570  p.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+5850
000000F85A0FF900  000002E781382A10  .*8.ç...  "gcf"
000000F85A0FF908  000002E78138DED0  ÐÞ8.ç...  "(Ljava/lang/Class;)[Ljava/lang/String;"
000000F85A0FF910  000002E7805596F0  ð.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+59D0
000000F85A0FF918  000002E7813870D0  Ðp8.ç...  "gcm"
000000F85A0FF920  000002E78136D020   Ð6.ç...  "(Ljava/lang/Class;)[Ljava/lang/String;"
000000F85A0FF928  000002E780559890  ..U.ç...  vape.unsigned __int64 __cdecl tim(void *)+5B70
000000F85A0FF930  000002E7805FDB70  pÛ_.ç...  "ds"
000000F85A0FF938  000002E781380B40  @.8.ç...  "(ILjava/lang/String;DDI)I"
000000F85A0FF940  000002E780559A30  0.U.ç...  L"襌⑌䐠䒉ᠤ襈⑔䠐䲉ࠤ荈壬荈⑼xݵ쀳鋩"
000000F85A0FF948  000002E781386D40  @m8.ç...  "gsw"
000000F85A0FF950  000002E781382730  0'8.ç...  "(ILjava/lang/String;)D"
000000F85A0FF958  000002E780559AF0  ð.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+5DD0
000000F85A0FF960  000002E78139D030  0Ð9.ç...  "gsh"
000000F85A0FF968  000002E781368AE0  à.6.ç...  "(ILjava/lang/String;)D"
000000F85A0FF970  000002E780559BA0   .U.ç...  vape.unsigned __int64 __cdecl tim(void *)+5E80
000000F85A0FF978  000002E781387040  @p8.ç...  "smd"
000000F85A0FF980  000002E78133D120   Ñ3.ç...  "(II)V"
000000F85A0FF988  000002E780559D10  ..U.ç...  vape.unsigned __int64 __cdecl tim(void *)+5FF0
000000F85A0FF990  000002E7805FDBDC  ÜÛ_.ç...  "gk"
000000F85A0FF998  000002E78136D950  PÙ6.ç...  "()I"
000000F85A0FF9A0  000002E780559DC0  À.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+60A0
000000F85A0FF9A8  000002E7805FDBE4  äÛ_.ç...  "gp"
000000F85A0FF9B0  000002E78137FAF0  ðú7.ç...  "(Ljava/lang/String;)Ljava/lang/String;"
000000F85A0FF9B8  000002E780559DE0  à.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+60C0
000000F85A0FF9C0  000002E7805FDC10  .Ü_.ç...  "su"
000000F85A0FF9C8  000002E78137C0B0  °À7.ç...  "(Ljava/lang/String;)V"
000000F85A0FF9D0  000002E780559F10  ..U.ç...  vape.unsigned __int64 __cdecl tim(void *)+61F0
000000F85A0FF9D8  000002E7805FDC30  0Ü_.ç...  "iv"
000000F85A0FF9E0  000002E78135D2E0  àÒ5.ç...  "()Z"
000000F85A0FF9E8  000002E780559F90  ..U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6270
000000F85A0FF9F0  000002E78137F9A0   ù7.ç...  "gvc"
000000F85A0FF9F8  000002E7813821C0  À!8.ç...  "(Ljava/lang/String;)Ljava/lang/Class;"
000000F85A0FFA00  000002E780559FB0  °.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6290
000000F85A0FFA08  000002E78135DF50  Pß5.ç...  "gmv"
000000F85A0FFA10  000002E781387C60  `|8.ç...  "()I"
000000F85A0FFA18  000002E78055A1D0  СU.ç...  vape.unsigned __int64 __cdecl tim(void *)+64B0
000000F85A0FFA20  000002E78137A230  0¢7.ç...  "rsc"
000000F85A0FFA28  000002E781386C20   l8.ç...  "()V"
000000F85A0FFA30  000002E78055A1F0  ð¡U.ç...  vape.unsigned __int64 __cdecl tim(void *)+64D0
000000F85A0FFA38  000002E7805FDC78  xÜ_.ç...  "mf"
000000F85A0FFA40  000002E781367880  .x6.ç...  "(IILjava/lang/String;)I"
000000F85A0FFA48  000002E780559C40  @.U.ç...  vape.unsigned __int64 __cdecl tim(void *)+5F20
000000F85A0FFA50  000002E7813670B0  °p6.ç...  "updc"
000000F85A0FFA58  000002E78137A440  @¤7.ç...  "(Ljava/lang/String;Ljava/lang/String;)V"
000000F85A0FFA60  000002E78055A220   ¢U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6500
000000F85A0FFA68  000002E78136D170  pÑ6.ç...  "mvk"
000000F85A0FFA70  000002E781387C00  .|8.ç...  "(II)I"
000000F85A0FFA78  000002E78055A240  @¢U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6520
000000F85A0FFA80  000002E78135BC50  P¼5.ç...  "gkn"
000000F85A0FFA88  000002E78137B570  pµ7.ç...  "(J)Ljava/lang/String;"
000000F85A0FFA90  000002E78055A270  p¢U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6550
000000F85A0FFA98  000002E7805FDCF0  ðÜ_.ç...  "rs"
000000F85A0FFAA0  000002E78138BAE0  àº8.ç...  "(IDD)V"
000000F85A0FFAA8  000002E78055A300  .£U.ç...  vape.unsigned __int64 __cdecl tim(void *)+65E0
000000F85A0FFAB0  000002E78136EC40  @ì6.ç...  "gts"
000000F85A0FFAB8  000002E781395050  PP9.ç...  "()I"
000000F85A0FFAC0  000002E78055A4C0  À¤U.ç...  vape.unsigned __int64 __cdecl tim(void *)+67A0
000000F85A0FFAC8  000002E781366C50  Pl6.ç...  "sts"
000000F85A0FFAD0  000002E7813823A0   #8.ç...  "()I"
000000F85A0FFAD8  000002E78055A520   ¥U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6800
000000F85A0FFAE0  000002E7813675B0  °u6.ç...  "trs"
000000F85A0FFAE8  000002E78137A5D0  Ð¥7.ç...  "(I)V"
000000F85A0FFAF0  000002E78055A560  `¥U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6840
000000F85A0FFAF8  000002E7813658A0   X6.ç...  "gfb"
000000F85A0FFB00  000002E781380610  ..8.ç...  "(Ljava/lang/String;)[B"
000000F85A0FFB08  000002E78055A590  .¥U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6870
000000F85A0FFB10  000002E78137F920   ù7.ç...  "gtcf"
000000F85A0FFB18  000002E781389EB0  °.8.ç...  "(Ljava/lang/Object;II)Z"
000000F85A0FFB20  000002E78055A6D0  ЦU.ç...  vape.unsigned __int64 __cdecl tim(void *)+69B0
000000F85A0FFB28  000002E78133D1D0  ÐÑ3.ç...  "gat"
000000F85A0FFB30  000002E78138B470  p´8.ç...  "()Ljava/lang/String;"
000000F85A0FFB38  000002E78055A660  `¦U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6940
000000F85A0FFB40  000002E78137FFF0  ðÿ7.ç...  "scm"
000000F85A0FFB48  000002E78137B660  `¶7.ç...  "(Ljava/lang/String;Ljava/lang/String;)V"
000000F85A0FFB50  000002E78055A930  0©U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6C10
000000F85A0FFB58  000002E781389DC0  À.8.ç...  "gls"
000000F85A0FFB60  000002E78136D110  .Ñ6.ç...  "()[Z"
000000F85A0FFB68  000002E78055A820   ¨U.ç...  vape.unsigned __int64 __cdecl tim(void *)+6B00
000000F85A0FFB70  000002E78137A320   £7.ç...  "sce"
000000F85A0FFB78  000002E78139E3B0  °ã9.ç...  "(Ljava/lang/String;)V"
000000F85A0FFB80  000002E78055AA90  .ªU.ç...  vape.unsigned __int64 __cdecl tim(void *)+6D70

第二批

000000F85A0FF590  000002E7805FC584  .Å_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8864
000000F85A0FF598  000002E7805FC588  .Å_.ç...  "(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;Z)V"
000000F85A0FF5A0  000002E780548590  ..T.ç...  L"襌⑌䐠䒉ᠤ襈⑔䠐䲉ࠤ荈磬ᢹ"
000000F85A0FF5A8  000002E7805FC5C4  ÄÅ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A88A4
000000F85A0FF5B0  000002E7805FC5C8  ÈÅ_.ç...  "(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;Z)V"
000000F85A0FF5B8  000002E780548700  ..T.ç...  L"襌⑌䐠䒉ᠤ襈⑔䠐䲉ࠤ荈棬ᢹ"
000000F85A0FF5C0  000002E7805FC604  .Æ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A88E4
000000F85A0FF5C8  000002E7805FC608  .Æ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)V"
000000F85A0FF5D0  000002E780546720   gT.ç...  vape.000002E780546720
000000F85A0FF5D8  000002E7805FC634  4Æ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8914
000000F85A0FF5E0  000002E7805FC638  8Æ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)Z"
000000F85A0FF5E8  000002E780546890  .hT.ç...  vape.000002E780546890
000000F85A0FF5F0  000002E7805FC664  dÆ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8944
000000F85A0FF5F8  000002E7805FC668  hÆ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)C"
000000F85A0FF600  000002E780546A10  .jT.ç...  vape.000002E780546A10
000000F85A0FF608  000002E7805FC694  .Æ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8974
000000F85A0FF610  000002E7805FC698  .Æ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)S"
000000F85A0FF618  000002E780546B90  .kT.ç...  vape.000002E780546B90
000000F85A0FF620  000002E7805FC6C4  ÄÆ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A89A4
000000F85A0FF628  000002E7805FC6C8  ÈÆ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)I"
000000F85A0FF630  000002E780546D10  .mT.ç...  vape.000002E780546D10
000000F85A0FF638  000002E7805FC6F4  ôÆ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A89D4
000000F85A0FF640  000002E7805FC6F8  øÆ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)J"
000000F85A0FF648  000002E780546E90  .nT.ç...  vape.000002E780546E90
000000F85A0FF650  000002E7805FC724  $Ç_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8A04
000000F85A0FF658  000002E7805FC728  (Ç_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)F"
000000F85A0FF660  000002E780547010  .pT.ç...  vape.000002E780547010
000000F85A0FF668  000002E7805FC754  TÇ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8A34
000000F85A0FF670  000002E7805FC758  XÇ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)D"
000000F85A0FF678  000002E780547190  .qT.ç...  vape.000002E780547190
000000F85A0FF680  000002E7805FC784  .Ç_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8A64
000000F85A0FF688  000002E7805FC788  .Ç_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
000000F85A0FF690  000002E780547490  .tT.ç...  vape.000002E780547490
000000F85A0FF698  000002E7805FC7C4  ÄÇ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8AA4
000000F85A0FF6A0  000002E7805FC7C8  ÈÇ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)[Z"
000000F85A0FF6A8  000002E780547490  .tT.ç...  vape.000002E780547490
000000F85A0FF6B0  000002E7805FC7F4  ôÇ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8AD4
000000F85A0FF6B8  000002E7805FC7F8  øÇ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)[C"
000000F85A0FF6C0  000002E780547490  .tT.ç...  vape.000002E780547490
000000F85A0FF6C8  000002E7805FC824  $È_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8B04
000000F85A0FF6D0  000002E7805FC828  (È_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)[S"
000000F85A0FF6D8  000002E780547490  .tT.ç...  vape.000002E780547490
000000F85A0FF6E0  000002E7805FC854  TÈ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8B34
000000F85A0FF6E8  000002E7805FC858  XÈ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)[I"
000000F85A0FF6F0  000002E780547490  .tT.ç...  vape.000002E780547490
000000F85A0FF6F8  000002E7805FC884  .È_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8B64
000000F85A0FF700  000002E7805FC888  .È_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)[J"
000000F85A0FF708  000002E780547490  .tT.ç...  vape.000002E780547490
000000F85A0FF710  000002E7805FC8B4  ´È_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8B94
000000F85A0FF718  000002E7805FC8B8  ¸È_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)[F"
000000F85A0FF720  000002E780547490  .tT.ç...  vape.000002E780547490
000000F85A0FF728  000002E7805FC8E4  äÈ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8BC4
000000F85A0FF730  000002E7805FC8E8  èÈ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)[D"
000000F85A0FF738  000002E780547490  .tT.ç...  vape.000002E780547490
000000F85A0FF740  000002E7805FC914  .É_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8BF4
000000F85A0FF748  000002E7805FC918  .É_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)[Ljava/lang/Object;"
000000F85A0FF750  000002E780547490  .tT.ç...  vape.000002E780547490
000000F85A0FF758  000002E7805FC954  TÉ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8C34
000000F85A0FF760  000002E7805FC958  XÉ_.ç...  "(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;Z)V"
000000F85A0FF768  000002E780548810  ..T.ç...  L"襌⑌䐠䒉ᠤ襈⑔䠐䲉ࠤ荈磬₹"
000000F85A0FF770  000002E7805FC994  .É_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8C74
000000F85A0FF778  000002E7805FC998  .É_.ç...  "(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;Z)V"
000000F85A0FF780  000002E780548990  ..T.ç...  L"襌⑌䐠䒉ᠤ襈⑔䠐䲉ࠤ荈棬₹"
000000F85A0FF788  000002E7805FC9D4  ÔÉ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8CB4
000000F85A0FF790  000002E7805FC9D8  ØÉ_.ç...  "(ILjava/lang/Object;)Z"
000000F85A0FF798  000002E780547610  .vT.ç...  vape.000002E780547610
000000F85A0FF7A0  000002E7805FC9F0  ðÉ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8CD0
000000F85A0FF7A8  000002E7805FC9F8  øÉ_.ç...  "(ILjava/lang/Object;)C"
000000F85A0FF7B0  000002E7805476B0  °vT.ç...  vape.000002E7805476B0
000000F85A0FF7B8  000002E7805FCA10  .Ê_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8CF0
000000F85A0FF7C0  000002E7805FCA18  .Ê_.ç...  "(ILjava/lang/Object;)S"
000000F85A0FF7C8  000002E780547750  PwT.ç...  vape.000002E780547750
000000F85A0FF7D0  000002E7805FCA30  0Ê_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8D10
000000F85A0FF7D8  000002E7805FCA38  8Ê_.ç...  "(ILjava/lang/Object;)I"
000000F85A0FF7E0  000002E7805477F0  ðwT.ç...  vape.000002E7805477F0
000000F85A0FF7E8  000002E7805FCA50  PÊ_.ç...  vape.unsigned __int64 __cdecl tim(void *)+A8D30
000000F85A0FF7F0  000002E7805FCA58  XÊ_.ç...  "(ILjava/lang/Object;)J"
000000F85A0FF7F8  000002E780547890  .xT.ç...  vape.000002E780547890
000000F85A0FF800  000002E7805FCA70  pÊ_.ç...  "aa"
000000F85A0FF808  000002E7805FCA78  xÊ_.ç...  "(ILjava/lang/Object;)F"
000000F85A0FF810  000002E780547930  0yT.ç...  vape.000002E780547930
000000F85A0FF818  000002E7805FCA90  .Ê_.ç...  "bb"
000000F85A0FF820  000002E7805FCA98  .Ê_.ç...  "(ILjava/lang/Object;)D"
000000F85A0FF828  000002E7805479E0  àyT.ç...  vape.000002E7805479E0
000000F85A0FF830  000002E7805FCAB0  °Ê_.ç...  "cc"
000000F85A0FF838  000002E7805FCAB8  ¸Ê_.ç...  "(ILjava/lang/Object;)Ljava/lang/Object;"
000000F85A0FF840  000002E780547B30  0{T.ç...  vape.000002E780547B30
000000F85A0FF848  000002E7805FCAE0  àÊ_.ç...  "dd"
000000F85A0FF850  000002E7805FCAE8  èÊ_.ç...  "(ILjava/lang/Object;)[Z"
000000F85A0FF858  000002E780547B30  0{T.ç...  vape.000002E780547B30
000000F85A0FF860  000002E7805FCB00  .Ë_.ç...  "ee"
000000F85A0FF868  000002E7805FCB08  .Ë_.ç...  "(ILjava/lang/Object;)[C"
000000F85A0FF870  000002E780547B30  0{T.ç...  vape.000002E780547B30
000000F85A0FF878  000002E7805FCB20   Ë_.ç...  "ff"
000000F85A0FF880  000002E7805FCB28  (Ë_.ç...  "(ILjava/lang/Object;)[S"
000000F85A0FF888  000002E780547B30  0{T.ç...  vape.000002E780547B30
000000F85A0FF890  000002E7805FCB40  @Ë_.ç...  "gg"
000000F85A0FF898  000002E7805FCB48  HË_.ç...  "(ILjava/lang/Object;)[I"
000000F85A0FF8A0  000002E780547B30  0{T.ç...  vape.000002E780547B30
000000F85A0FF8A8  000002E7805FCB60  `Ë_.ç...  "hh"
000000F85A0FF8B0  000002E7805FCB68  hË_.ç...  "(ILjava/lang/Object;)[J"
000000F85A0FF8B8  000002E780547B30  0{T.ç...  vape.000002E780547B30
000000F85A0FF8C0  000002E7805FCB80  .Ë_.ç...  "ii"
000000F85A0FF8C8  000002E7805FCB88  .Ë_.ç...  "(ILjava/lang/Object;)[F"
000000F85A0FF8D0  000002E780547B30  0{T.ç...  vape.000002E780547B30
000000F85A0FF8D8  000002E7805FCBA0   Ë_.ç...  "jj"
000000F85A0FF8E0  000002E7805FCBA8  ¨Ë_.ç...  "(ILjava/lang/Object;)[D"
000000F85A0FF8E8  000002E780547B30  0{T.ç...  vape.000002E780547B30
000000F85A0FF8F0  000002E7805FCBC0  ÀË_.ç...  "kk"
000000F85A0FF8F8  000002E7805FCBC8  ÈË_.ç...  "(ILjava/lang/Object;)[Ljava/lang/Object;"
000000F85A0FF900  000002E780547B30  0{T.ç...  vape.000002E780547B30
000000F85A0FF908  000002E7805FCBF4  ôË_.ç...  "ll"
000000F85A0FF910  000002E7805FCBF8  øË_.ç...  "(ILjava/lang/Object;Z)V"
000000F85A0FF918  000002E780547BD0  Ð{T.ç...  vape.000002E780547BD0
000000F85A0FF920  000002E7805FCC10  .Ì_.ç...  "mm"
000000F85A0FF928  000002E7805FCC18  .Ì_.ç...  "(ILjava/lang/Object;C)V"
000000F85A0FF930  000002E780547C70  p|T.ç...  vape.000002E780547C70
000000F85A0FF938  000002E7805FCC30  0Ì_.ç...  "nn"
000000F85A0FF940  000002E7805FCC38  8Ì_.ç...  "(ILjava/lang/Object;S)V"
000000F85A0FF948  000002E780547D10  .}T.ç...  vape.000002E780547D10
000000F85A0FF950  000002E7805FCC50  PÌ_.ç...  "oo"
000000F85A0FF958  000002E7805FCC58  XÌ_.ç...  "(ILjava/lang/Object;I)V"
000000F85A0FF960  000002E780547DB0  °}T.ç...  vape.000002E780547DB0
000000F85A0FF968  000002E7805FCC70  pÌ_.ç...  "pp"
000000F85A0FF970  000002E7805FCC78  xÌ_.ç...  "(ILjava/lang/Object;J)V"
000000F85A0FF978  000002E780547E50  P~T.ç...  vape.000002E780547E50
000000F85A0FF980  000002E7805FCC90  .Ì_.ç...  "qq"
000000F85A0FF988  000002E7805FCC98  .Ì_.ç...  "(ILjava/lang/Object;F)V"
000000F85A0FF990  000002E780547EF0  ð~T.ç...  vape.000002E780547EF0
000000F85A0FF998  000002E7805FCCB0  °Ì_.ç...  "rr"
000000F85A0FF9A0  000002E7805FCCB8  ¸Ì_.ç...  "(ILjava/lang/Object;D)V"
000000F85A0FF9A8  000002E780547F90  ..T.ç...  vape.000002E780547F90
000000F85A0FF9B0  000002E7805FCCD0  ÐÌ_.ç...  "ss"
000000F85A0FF9B8  000002E7805FCCD8  ØÌ_.ç...  "(ILjava/lang/Object;Ljava/lang/Object;)V"
000000F85A0FF9C0  000002E7805480D0  Ð.T.ç...  vape.000002E7805480D0
000000F85A0FF9C8  000002E7805FCD04  .Í_.ç...  "tt"
000000F85A0FF9D0  000002E7805FCD08  .Í_.ç...  "(ILjava/lang/Object;[Z)V"
000000F85A0FF9D8  000002E7805480D0  Ð.T.ç...  vape.000002E7805480D0
000000F85A0FF9E0  000002E7805FCD24  $Í_.ç...  "uu"
000000F85A0FF9E8  000002E7805FCD28  (Í_.ç...  "(ILjava/lang/Object;[C)V"
000000F85A0FF9F0  000002E7805480D0  Ð.T.ç...  vape.000002E7805480D0
000000F85A0FF9F8  000002E7805FCD44  DÍ_.ç...  "vv"
000000F85A0FFA00  000002E7805FCD48  HÍ_.ç...  "(ILjava/lang/Object;[S)V"
000000F85A0FFA08  000002E7805480D0  Ð.T.ç...  vape.000002E7805480D0
000000F85A0FFA10  000002E7805FCD64  dÍ_.ç...  "ww"
000000F85A0FFA18  000002E7805FCD68  hÍ_.ç...  "(ILjava/lang/Object;[I)V"
000000F85A0FFA20  000002E7805480D0  Ð.T.ç...  vape.000002E7805480D0
000000F85A0FFA28  000002E7805FCD84  .Í_.ç...  "xx"
000000F85A0FFA30  000002E7805FCD88  .Í_.ç...  "(ILjava/lang/Object;[J)V"
000000F85A0FFA38  000002E7805480D0  Ð.T.ç...  vape.000002E7805480D0
000000F85A0FFA40  000002E7805FCDA4  ¤Í_.ç...  "yy"
000000F85A0FFA48  000002E7805FCDA8  ¨Í_.ç...  "(ILjava/lang/Object;[F)V"
000000F85A0FFA50  000002E7805480D0  Ð.T.ç...  vape.000002E7805480D0
000000F85A0FFA58  000002E7805FCDC4  ÄÍ_.ç...  "zz"
000000F85A0FFA60  000002E7805FCDC8  ÈÍ_.ç...  "(ILjava/lang/Object;[D)V"
000000F85A0FFA68  000002E7805480D0  Ð.T.ç...  vape.000002E7805480D0
000000F85A0FFA70  000002E7805FCDE4  äÍ_.ç...  "aaa"
000000F85A0FFA78  000002E7805FCDE8  èÍ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)V"
000000F85A0FFA80  000002E7805480D0  Ð.T.ç...  vape.000002E7805480D0
000000F85A0FFA88  000002E7805FCE14  .Î_.ç...  "bbb"
000000F85A0FFA90  000002E7805FCE18  .Î_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)V"
000000F85A0FFA98  000002E780548170  p.T.ç...  vape.000002E780548170
000000F85A0FFAA0  000002E7805FCE44  DÎ_.ç...  "ccc"
000000F85A0FFAA8  000002E7805FCE48  HÎ_.ç...  "(ILjava/lang/Class;[Ljava/lang/Object;)Ljava/lang/Object;"
000000F85A0FFAB0  000002E780548450  P.T.ç...  vape.000002E780548450
000000F85A0FFAB8  000002E7805FCE84  .Î_.ç...  "ddd"
000000F85A0FFAC0  000002E7805FCE88  .Î_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)B"
000000F85A0FFAC8  000002E780547310  .sT.ç...  vape.000002E780547310
000000F85A0FFAD0  000002E7805FCEB4  ´Î_.ç...  "eee"
000000F85A0FFAD8  000002E7805FCEB8  ¸Î_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)[B"
000000F85A0FFAE0  000002E780547490  .tT.ç...  vape.000002E780547490
000000F85A0FFAE8  000002E7805FCEE4  äÎ_.ç...  "fff"
000000F85A0FFAF0  000002E7805FCEE8  èÎ_.ç...  "(ILjava/lang/Object;)B"
000000F85A0FFAF8  000002E780547A90  .zT.ç...  vape.000002E780547A90
000000F85A0FFB00  000002E7805FCF00  .Ï_.ç...  "ggg"
000000F85A0FFB08  000002E7805FCF08  .Ï_.ç...  "(ILjava/lang/Object;B)V"
000000F85A0FFB10  000002E780548030  0.T.ç...  vape.000002E780548030
000000F85A0FFB18  000002E7805FCF20   Ï_.ç...  "hhh"
000000F85A0FFB20  000002E7805FCF28  (Ï_.ç...  "(ILjava/lang/Object;)[B"
000000F85A0FFB28  000002E780547B30  0{T.ç...  vape.000002E780547B30
000000F85A0FFB30  000002E7805FCF40  @Ï_.ç...  "iii"
000000F85A0FFB38  000002E7805FCF48  HÏ_.ç...  "(ILjava/lang/Object;[B)V"
000000F85A0FFB40  000002E7805480D0  Ð.T.ç...  vape.000002E7805480D0
000000F85A0FFB48  000002E7805FCF64  dÏ_.ç...  "jjj"
000000F85A0FFB50  000002E7805FCF68  hÏ_.ç...  "(ILjava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"
000000F85A0FFB58  000002E7805482E0  à.T.ç...  vape.000002E7805482E0
000000F85A0FFB60  000002E7805FCFA4  ¤Ï_.ç...  "gfn"
000000F85A0FFB68  000002E7805FCFA8  ¨Ï_.ç...  "(I)Ljava/lang/String;"
000000F85A0FFB70  000002E780548AB0  °.T.ç...  vape.000002E780548AB0
000000F85A0FFB78  000002E7805FCFC0  ÀÏ_.ç...  "gmn"
000000F85A0FFB80  000002E7805FCFC8  ÈÏ_.ç...  "(I)Ljava/lang/String;"
000000F85A0FFB88  000002E780548BB0  °.T.ç...  vape.000002E780548BB0

如果Hook的话,x64dbg.exe迭代这些内容并不方便,我们采用下面这种方案来简便输出。

我们找到RegisterNatives的实现,可以观察到它自带一个for循环,我们找准点Hook输出即可。

JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz,
                                    const JNINativeMethod *methods,
                                    jint nMethods))
  HOTSPOT_JNI_REGISTERNATIVES_ENTRY(env, clazz, (void *) methods, nMethods);
  jint ret = 0;
  DT_RETURN_MARK(RegisterNatives, jint, (const jint&)ret);

  Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));

  // There are no restrictions on native code registering native methods,
  // which allows agents to redefine the bindings to native methods, however
  // we issue a warning if any code running outside of the boot/platform
  // loader is rebinding any native methods in classes loaded by the
  // boot/platform loader that are in named modules. That will catch changes
  // to platform classes while excluding classes added to the bootclasspath.
  bool do_warning = false;

  // Only instanceKlasses can have native methods
  if (k->is_instance_klass()) {
    oop cl = k->class_loader();
    InstanceKlass* ik = InstanceKlass::cast(k);
    // Check for a platform class
    if ((cl ==  NULL || SystemDictionary::is_platform_class_loader(cl)) &&
        ik->module()->is_named()) {
      Klass* caller = thread->security_get_caller_class(1);
      // If no caller class, or caller class has a different loader, then
      // issue a warning below.
      do_warning = (caller == NULL) || caller->class_loader() != cl;
    }
  }


  for (int index = 0; index < nMethods; index++) {
    const char* meth_name = methods[index].name;
    const char* meth_sig = methods[index].signature;
    int meth_name_len = (int)strlen(meth_name);

    // The class should have been loaded (we have an instance of the class
    // passed in) so the method and signature should already be in the symbol
    // table.  If they're not there, the method doesn't exist.
    TempNewSymbol  name = SymbolTable::probe(meth_name, meth_name_len);
    TempNewSymbol  signature = SymbolTable::probe(meth_sig, (int)strlen(meth_sig));

    if (name == NULL || signature == NULL) {
      ResourceMark rm(THREAD);
      stringStream st;
      st.print("Method %s.%s%s not found", k->external_name(), meth_name, meth_sig);
      // Must return negative value on failure
      THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), -1);
    }

    if (do_warning) {
      ResourceMark rm(THREAD);
      log_warning(jni, resolve)("Re-registering of platform native method: %s.%s%s "
              "from code in a different classloader", k->external_name(), meth_name, meth_sig);
    }

    bool res = Method::register_native(k, name, signature,
                                       (address) methods[index].fnPtr, THREAD);
    if (!res) {
      ret = -1;
      break;
    }
  }
  return ret;
JNI_END

At Jvm.dll FileOffset=0x492BB0

RegisterNative('{utf8@[r12-0x10]}', '{utf8@[r12-0x8]}', {p:[r12]} (RVA=0x{x:([r12] - ModBase)}))
RegisterNative('exit', '(Z)V', 0000021E80EF8190 (RVA=0x28190))
RegisterNative('dc', '()V', 0000021E80EF8200 (RVA=0x28200))
RegisterNative('fs', '()V', 0000021E80EF8230 (RVA=0x28230))
RegisterNative('gc', '(Ljava/lang/String;)Ljava/lang/Class;', 0000021E80EF8270 (RVA=0x28270))
RegisterNative('gt', '(Ljava/lang/String;)[B', 0000021E80EF82E0 (RVA=0x282E0))
RegisterNative('gs', '()Ljava/lang/String;', 0000021E80EF8300 (RVA=0x28300))
RegisterNative('ss', '(Ljava/lang/String;)V', 0000021E80EF8330 (RVA=0x28330))
RegisterNative('ss_2', '(Ljava/lang/String;)I', 0000021E80EF83C0 (RVA=0x283C0))
RegisterNative('ss_3', '(Ljava/lang/String;)I', 0000021E80EF8470 (RVA=0x28470))
RegisterNative('gcj', '(Ljava/lang/String;)Ljava/lang/Class;', 0000021E80EF85E0 (RVA=0x285E0))
RegisterNative('gcs', '(Ljava/lang/Class;)Ljava/lang/String;', 0000021E80EF8670 (RVA=0x28670))
RegisterNative('cs', '(I)Ljava/lang/String;', 0000021E80EF87F0 (RVA=0x287F0))
RegisterNative('rl', '()V', 0000021E80ED69C0 (RVA=0x69C0))
RegisterNative('mb', '(I)V', 0000021E80EF8590 (RVA=0x28590))
RegisterNative('grh', '()Ljava/lang/Object;', 0000021E80EF8830 (RVA=0x28830))
RegisterNative('cpy', '(Ljava/lang/String;)V', 0000021E80EF8850 (RVA=0x28850))
RegisterNative('gks', '(I)S', 0000021E80EF8A30 (RVA=0x28A30))
RegisterNative('p', '(Ljava/lang/String;)V', 0000021E80EF89D0 (RVA=0x289D0))
RegisterNative('gco', '(Ljava/lang/Class;)[Ljava/lang/Object;', 0000021E80EF8AB0 (RVA=0x28AB0))
RegisterNative('trn', '(DDD)[D', 0000021E80EF8CA0 (RVA=0x28CA0))
RegisterNative('gcb', '(Ljava/lang/Class;)[B', 0000021E80EF93C0 (RVA=0x293C0))
RegisterNative('scb', '(Ljava/lang/Class;[B)I', 0000021E80EF9570 (RVA=0x29570))
RegisterNative('gcf', '(Ljava/lang/Class;)[Ljava/lang/String;', 0000021E80EF96F0 (RVA=0x296F0))
RegisterNative('gcm', '(Ljava/lang/Class;)[Ljava/lang/String;', 0000021E80EF9890 (RVA=0x29890))
RegisterNative('ds', '(ILjava/lang/String;DDI)I', 0000021E80EF9A30 (RVA=0x29A30))
RegisterNative('gsw', '(ILjava/lang/String;)D', 0000021E80EF9AF0 (RVA=0x29AF0))
RegisterNative('gsh', '(ILjava/lang/String;)D', 0000021E80EF9BA0 (RVA=0x29BA0))
RegisterNative('smd', '(II)V', 0000021E80EF9D10 (RVA=0x29D10))
RegisterNative('gk', '()I', 0000021E80EF9DC0 (RVA=0x29DC0))
RegisterNative('gp', '(Ljava/lang/String;)Ljava/lang/String;', 0000021E80EF9DE0 (RVA=0x29DE0))
RegisterNative('su', '(Ljava/lang/String;)V', 0000021E80EF9F10 (RVA=0x29F10))
RegisterNative('iv', '()Z', 0000021E80EF9F90 (RVA=0x29F90))
RegisterNative('gvc', '(Ljava/lang/String;)Ljava/lang/Class;', 0000021E80EF9FB0 (RVA=0x29FB0))
RegisterNative('gmv', '()I', 0000021E80EFA1D0 (RVA=0x2A1D0))
RegisterNative('rsc', '()V', 0000021E80EFA1F0 (RVA=0x2A1F0))
RegisterNative('mf', '(IILjava/lang/String;)I', 0000021E80EF9C40 (RVA=0x29C40))
RegisterNative('updc', '(Ljava/lang/String;Ljava/lang/String;)V', 0000021E80EFA220 (RVA=0x2A220))
RegisterNative('mvk', '(II)I', 0000021E80EFA240 (RVA=0x2A240))
RegisterNative('gkn', '(J)Ljava/lang/String;', 0000021E80EFA270 (RVA=0x2A270))
RegisterNative('rs', '(IDD)V', 0000021E80EFA300 (RVA=0x2A300))
RegisterNative('gts', '()I', 0000021E80EFA4C0 (RVA=0x2A4C0))
RegisterNative('sts', '()I', 0000021E80EFA520 (RVA=0x2A520))
RegisterNative('trs', '(I)V', 0000021E80EFA560 (RVA=0x2A560))
RegisterNative('gfb', '(Ljava/lang/String;)[B', 0000021E80EFA590 (RVA=0x2A590))
RegisterNative('gtcf', '(Ljava/lang/Object;II)Z', 0000021E80EFA6D0 (RVA=0x2A6D0))
RegisterNative('gat', '()Ljava/lang/String;', 0000021E80EFA660 (RVA=0x2A660))
RegisterNative('scm', '(Ljava/lang/String;Ljava/lang/String;)V', 0000021E80EFA930 (RVA=0x2A930))
RegisterNative('gls', '()[Z', 0000021E80EFA820 (RVA=0x2A820))
RegisterNative('sce', '(Ljava/lang/String;)V', 0000021E80EFAA90 (RVA=0x2AA90))
RegisterNative('a', '(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;Z)V', 0000021E80EE8590 (RVA=0x18590))
RegisterNative('b', '(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;Z)V', 0000021E80EE8700 (RVA=0x18700))
RegisterNative('c', '(ILjava/lang/Object;[Ljava/lang/Object;)V', 0000021E80EE6720 (RVA=0x16720))
RegisterNative('d', '(ILjava/lang/Object;[Ljava/lang/Object;)Z', 0000021E80EE6890 (RVA=0x16890))
RegisterNative('e', '(ILjava/lang/Object;[Ljava/lang/Object;)C', 0000021E80EE6A10 (RVA=0x16A10))
RegisterNative('f', '(ILjava/lang/Object;[Ljava/lang/Object;)S', 0000021E80EE6B90 (RVA=0x16B90))
RegisterNative('g', '(ILjava/lang/Object;[Ljava/lang/Object;)I', 0000021E80EE6D10 (RVA=0x16D10))
RegisterNative('h', '(ILjava/lang/Object;[Ljava/lang/Object;)J', 0000021E80EE6E90 (RVA=0x16E90))
RegisterNative('i', '(ILjava/lang/Object;[Ljava/lang/Object;)F', 0000021E80EE7010 (RVA=0x17010))
RegisterNative('j', '(ILjava/lang/Object;[Ljava/lang/Object;)D', 0000021E80EE7190 (RVA=0x17190))
RegisterNative('k', '(ILjava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;', 0000021E80EE7490 (RVA=0x17490))
RegisterNative('l', '(ILjava/lang/Object;[Ljava/lang/Object;)[Z', 0000021E80EE7490 (RVA=0x17490))
RegisterNative('m', '(ILjava/lang/Object;[Ljava/lang/Object;)[C', 0000021E80EE7490 (RVA=0x17490))
RegisterNative('n', '(ILjava/lang/Object;[Ljava/lang/Object;)[S', 0000021E80EE7490 (RVA=0x17490))
RegisterNative('o', '(ILjava/lang/Object;[Ljava/lang/Object;)[I', 0000021E80EE7490 (RVA=0x17490))
RegisterNative('p', '(ILjava/lang/Object;[Ljava/lang/Object;)[J', 0000021E80EE7490 (RVA=0x17490))
RegisterNative('q', '(ILjava/lang/Object;[Ljava/lang/Object;)[F', 0000021E80EE7490 (RVA=0x17490))
RegisterNative('r', '(ILjava/lang/Object;[Ljava/lang/Object;)[D', 0000021E80EE7490 (RVA=0x17490))
RegisterNative('s', '(ILjava/lang/Object;[Ljava/lang/Object;)[Ljava/lang/Object;', 0000021E80EE7490 (RVA=0x17490))
RegisterNative('t', '(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;Z)V', 0000021E80EE8810 (RVA=0x18810))
RegisterNative('u', '(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;Z)V', 0000021E80EE8990 (RVA=0x18990))
RegisterNative('v', '(ILjava/lang/Object;)Z', 0000021E80EE7610 (RVA=0x17610))
RegisterNative('w', '(ILjava/lang/Object;)C', 0000021E80EE76B0 (RVA=0x176B0))
RegisterNative('x', '(ILjava/lang/Object;)S', 0000021E80EE7750 (RVA=0x17750))
RegisterNative('y', '(ILjava/lang/Object;)I', 0000021E80EE77F0 (RVA=0x177F0))
RegisterNative('z', '(ILjava/lang/Object;)J', 0000021E80EE7890 (RVA=0x17890))
RegisterNative('aa', '(ILjava/lang/Object;)F', 0000021E80EE7930 (RVA=0x17930))
RegisterNative('bb', '(ILjava/lang/Object;)D', 0000021E80EE79E0 (RVA=0x179E0))
RegisterNative('cc', '(ILjava/lang/Object;)Ljava/lang/Object;', 0000021E80EE7B30 (RVA=0x17B30))
RegisterNative('dd', '(ILjava/lang/Object;)[Z', 0000021E80EE7B30 (RVA=0x17B30))
RegisterNative('ee', '(ILjava/lang/Object;)[C', 0000021E80EE7B30 (RVA=0x17B30))
RegisterNative('ff', '(ILjava/lang/Object;)[S', 0000021E80EE7B30 (RVA=0x17B30))
RegisterNative('gg', '(ILjava/lang/Object;)[I', 0000021E80EE7B30 (RVA=0x17B30))
RegisterNative('hh', '(ILjava/lang/Object;)[J', 0000021E80EE7B30 (RVA=0x17B30))
RegisterNative('ii', '(ILjava/lang/Object;)[F', 0000021E80EE7B30 (RVA=0x17B30))
RegisterNative('jj', '(ILjava/lang/Object;)[D', 0000021E80EE7B30 (RVA=0x17B30))
RegisterNative('kk', '(ILjava/lang/Object;)[Ljava/lang/Object;', 0000021E80EE7B30 (RVA=0x17B30))
RegisterNative('ll', '(ILjava/lang/Object;Z)V', 0000021E80EE7BD0 (RVA=0x17BD0))
RegisterNative('mm', '(ILjava/lang/Object;C)V', 0000021E80EE7C70 (RVA=0x17C70))
RegisterNative('nn', '(ILjava/lang/Object;S)V', 0000021E80EE7D10 (RVA=0x17D10))
RegisterNative('oo', '(ILjava/lang/Object;I)V', 0000021E80EE7DB0 (RVA=0x17DB0))
RegisterNative('pp', '(ILjava/lang/Object;J)V', 0000021E80EE7E50 (RVA=0x17E50))
RegisterNative('qq', '(ILjava/lang/Object;F)V', 0000021E80EE7EF0 (RVA=0x17EF0))
RegisterNative('rr', '(ILjava/lang/Object;D)V', 0000021E80EE7F90 (RVA=0x17F90))
RegisterNative('ss', '(ILjava/lang/Object;Ljava/lang/Object;)V', 0000021E80EE80D0 (RVA=0x180D0))
RegisterNative('tt', '(ILjava/lang/Object;[Z)V', 0000021E80EE80D0 (RVA=0x180D0))
RegisterNative('uu', '(ILjava/lang/Object;[C)V', 0000021E80EE80D0 (RVA=0x180D0))
RegisterNative('vv', '(ILjava/lang/Object;[S)V', 0000021E80EE80D0 (RVA=0x180D0))
RegisterNative('ww', '(ILjava/lang/Object;[I)V', 0000021E80EE80D0 (RVA=0x180D0))
RegisterNative('xx', '(ILjava/lang/Object;[J)V', 0000021E80EE80D0 (RVA=0x180D0))
RegisterNative('yy', '(ILjava/lang/Object;[F)V', 0000021E80EE80D0 (RVA=0x180D0))
RegisterNative('zz', '(ILjava/lang/Object;[D)V', 0000021E80EE80D0 (RVA=0x180D0))
RegisterNative('aaa', '(ILjava/lang/Object;[Ljava/lang/Object;)V', 0000021E80EE80D0 (RVA=0x180D0))
RegisterNative('bbb', '(ILjava/lang/Object;[Ljava/lang/Object;)V', 0000021E80EE8170 (RVA=0x18170))
RegisterNative('ccc', '(ILjava/lang/Class;[Ljava/lang/Object;)Ljava/lang/Object;', 0000021E80EE8450 (RVA=0x18450))
RegisterNative('ddd', '(ILjava/lang/Object;[Ljava/lang/Object;)B', 0000021E80EE7310 (RVA=0x17310))
RegisterNative('eee', '(ILjava/lang/Object;[Ljava/lang/Object;)[B', 0000021E80EE7490 (RVA=0x17490))
RegisterNative('fff', '(ILjava/lang/Object;)B', 0000021E80EE7A90 (RVA=0x17A90))
RegisterNative('ggg', '(ILjava/lang/Object;B)V', 0000021E80EE8030 (RVA=0x18030))
RegisterNative('hhh', '(ILjava/lang/Object;)[B', 0000021E80EE7B30 (RVA=0x17B30))
RegisterNative('iii', '(ILjava/lang/Object;[B)V', 0000021E80EE80D0 (RVA=0x180D0))
RegisterNative('jjj', '(ILjava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;', 0000021E80EE82E0 (RVA=0x182E0))
RegisterNative('gfn', '(I)Ljava/lang/String;', 0000021E80EE8AB0 (RVA=0x18AB0))
RegisterNative('gmn', '(I)Ljava/lang/String;', 0000021E80EE8BB0 (RVA=0x18BB0))

后续即可分析这些Native函数,只不过他们大部分都加了VM。

在注入后,主程序即可退出

部分 Native 函数解析
RegisterNative('cpy', '(Ljava/lang/String;)V', 0000021E80EF8850 (RVA=0x28850))
void __fastcall Java_a_a_cpy(JNIEnv *a1, __int64 a2, __int64 a3)
{
  int StringLength; // eax
  unsigned int v4; // eax
  _BYTE *v5; // [rsp+30h] [rbp-58h]
  __int64 v6; // [rsp+38h] [rbp-50h]
  HGLOBAL hMem; // [rsp+40h] [rbp-48h]

  StringLength = JNI_GetStringLength(a1, a3);
  v5 = sub_180032644(StringLength);
  v4 = JNI_GetStringLength(a1, a3);
  JNI_GetStringUTFRegion(a1, a3, 0, v4, v5);
  v5[JNI_GetStringLength(a1, a3)] = 0;
  v6 = -1LL;
  do
    ++v6;
  while ( v5[v6] );
  hMem = GlobalAlloc(2u, v6 + 1);
  qmemcpy(GlobalLock(hMem), v5, v6 + 1);
  GlobalUnlock(hMem);
  OpenClipboard(0LL);
  EmptyClipboard();
  SetClipboardData(1u, hMem);
  CloseClipboard();
  j_j_free(v5);
}
RegisterNative('rs', '(IDD)V', 0000021E80EFA300 (RVA=0x2A300))
void Java_a_a_rs(JNIEnv *env, jclass clazz, jint mode, jdouble width, jdouble height)
{
  BOOL changed;

  if ( !mode )
  {
    glGetFloatv(0xBA6u, &params);
    glGetFloatv(0xBA7u, &m);
  }
  if ( mode == 2 )
    glVertex2d(width, height);

  // Is Window Size Changed
  changed = last_width != width || last_height != height;
  if ( changed && !mode )
  {
    // ReInit
    a = glGenLists(1);
    glNewList(a, GL_COMPILE /* 0x1300 */);
    glMatrixMode(GL_PROJECTION /* 0x1701 */);
    glLoadIdentity();
    glOrtho(0.0d, width, height, 0.0d, 1500.0d, 3000.0d);
    glMatrixMode(GL_MODELVIEW /* 0x1700 */);
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -2000.0f);
    glEndList();
  }
  else
  {
    if ( mode )
    {
      glMatrixMode(0x1701u);
      glLoadMatrixf(&m);
      glMatrixMode(0x1700u);
      glLoadMatrixf(&params);
    }
    else
    {
      glCallList(list);
    }
    // Update Window Width & Height
    last_width = width;                         
    last_height = height;
  }
}
RegisterNative('mf', '(IILjava/lang/String;)I', 0000021E80EF9C40 (RVA=0x29C40))
void __fastcall Java_a_a_mf(JNIEnv *a1, jclass clazz, jint a3, jint a4, jstring fontName)
{
  void *p; // [rsp+20h] [rbp-28h]
  FontStruct *FontTexture; // [rsp+28h] [rbp-20h]
  char *StringUTFChars; // [rsp+30h] [rbp-18h]
  jint v9; // [rsp+60h] [rbp+18h] BYREF
  jint v10; // [rsp+68h] [rbp+20h]

  v10 = a4;
  v9 = a3;
  StringUTFChars = (char *)JNI_GetStringUTFChars(a1, fontName, 0LL);
  p = cxx::new(0x27120uLL);
  if ( p )
  {
    memzero(p, 0x27120uLL);
    FontTexture = loadFontTexture((FontStruct *)p, StringUTFChars, v10);
  }
  else
  {
    FontTexture = 0LL;
  }
  *(_QWORD *)sub_18002B460((__int64)&unk_180C16EC0, (__int64)&v9) = FontTexture;
  sub_18000DD60(a1, fontName, StringUTFChars);
  sub_18002B460((__int64)&unk_180C16EC0, (__int64)&v9);
}

FontStruct *__fastcall loadFontTexture(FontStruct *font, char *fontName, int fontSize)
{
  char *v3; // rax
  __int64 v4; // rcx
  unsigned __int8 v5; // dl
  int v6; // eax
  __int64 v7; // rax
  char *v8; // rax
  __int64 v9; // rcx
  __int64 v10; // rdx
  int v11; // eax
  __int64 v12; // rax
  void *v13; // rax
  int v15; // [rsp+50h] [rbp-468h]
  int v16; // [rsp+50h] [rbp-468h]
  char v17; // [rsp+57h] [rbp-461h]
  int j; // [rsp+58h] [rbp-460h]
  int v19; // [rsp+5Ch] [rbp-45Ch]
  _BYTE *pixels; // [rsp+60h] [rbp-458h]
  __int64 v21; // [rsp+78h] [rbp-440h]
  __int64 v22; // [rsp+80h] [rbp-438h]
  char i; // [rsp+90h] [rbp-428h] BYREF
  _BYTE v24[15]; // [rsp+91h] [rbp-427h] BYREF
  _BYTE v25[1024]; // [rsp+A0h] [rbp-418h] BYREF

  font->fontHandle = 0LL;
  memset(font->charWidths, 0, 0x9C40uLL);
  memset(&font->charHeights[16], 0, 0x9C40uLL);
  memset(&font->bitmapData[128], 0, 0x13880uLL);
  font[1].charWidths[24] = fontSize;
  font->textureResource = (void *)sub_18002DF60(512LL, 512LL, 1LL);
  memset(v25, 0, sizeof(v25));
  sub_18000E080(v25, "C:\\Windows\\Fonts\\%s.ttf", fontName);
  v3 = fontName;
  v4 = "proxima" - fontName;
  while ( 1 )
  {
    v5 = *v3;
    if ( *v3 != v3[v4] )
      break;
    ++v3;
    if ( !v5 )
    {
      v6 = 0;
      goto LABEL_6;
    }
  }
  v6 = v5 < (unsigned __int8)v3[v4] ? -1 : 1;
LABEL_6:
  if ( v6 )
  {
    v8 = fontName;
    v9 = "proximabd" - fontName;
    while ( 1 )
    {
      v10 = (unsigned __int8)*v8;
      if ( (_BYTE)v10 != v8[v9] )
        break;
      ++v8;
      if ( !(_BYTE)v10 )
      {
        v11 = 0;
        goto LABEL_13;
      }
    }
    v11 = (unsigned __int8)v10 < (unsigned __int8)v8[v9] ? -1 : 1;
LABEL_13:
    if ( v11 )
    {
      v13 = (void *)sub_18002EEF0(font->textureResource, v10, v25);
    }
    else
    {
      v12 = sub_180023B80();
      v13 = sub_18002EF90((__int64)font->textureResource, (float)fontSize, v12, 63116LL);
    }
    font->fontHandle = v13;
  }
  else
  {
    v7 = sub_180023B70();
    font->fontHandle = sub_18002EF90((__int64)font->textureResource, (float)fontSize, v7, 43240LL);
  }
  for ( i = 0; i != 127; ++i )
  {
    texture_font_load_face((_QWORD *)font->fontHandle, (__int64)&i);
    v21 = sub_18002E220(font->fontHandle, &i);
    font->charWidths[i] = *(_DWORD *)(v21 + 32);
  }
  for ( v24[0] = 0; v24[0] != 127; ++v24[0] )
  {
    texture_font_load_face((_QWORD *)font->fontHandle, (__int64)v24);
    v22 = sub_18002E220(font->fontHandle, v24);
    *(float *)&font->charHeights[v24[0] + 16] = (float)*(int *)(v22 + 28);
  }
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(0xBE2u);
  glBlendFunc(0x302u, 0x303u);
  glGenTextures(1, (GLuint *)&font[1].charWidths[25]);
  glBindTexture(0xDE1u, font[1].charWidths[25]);
  glTexParameteri(0xDE1u, 0x2802u, 10496);
  glTexParameteri(0xDE1u, 0x2803u, 10496);
  glTexParameteri(0xDE1u, 0x2800u, 9729);
  glTexParameteri(0xDE1u, 0x2801u, 9729);
  v19 = *(_DWORD *)(*((_QWORD *)font->fontHandle + 1) + 16LL) * *(_DWORD *)(*((_QWORD *)font->fontHandle + 1) + 8LL);
  pixels = j_cxx::new(4 * v19);
  v15 = 0;
  for ( j = 0; j < v19; ++j )
  {
    v17 = *(_BYTE *)(*(_QWORD *)(*((_QWORD *)font->fontHandle + 1) + 48LL) + j);
    pixels[v15] = -1;
    v16 = v15 + 1;
    pixels[v16++] = -1;
    pixels[v16++] = -1;
    pixels[v16] = v17;
    v15 = v16 + 1;
  }
  glTexImage2D(
    0xDE1u,
    0,
    6408,
    *(_DWORD *)(*((_QWORD *)font->fontHandle + 1) + 8LL),
    *(_DWORD *)(*((_QWORD *)font->fontHandle + 1) + 16LL),
    0,
    0x1908u,
    0x1401u,
    pixels);
  return font;
}

Vape.Jar

Zkm混淆,笔者目前没有接触过Java反混淆领域,暂时不写,具体附件在“相关附件”栏,Java大手子们可以尝试。

分析 VapeLite

主程序

主程序采用 Themida 加壳,有反调试,API Wrapper,资源压缩等,部分代码虚拟化。脱壳后即可继续分析。

VapeLite主程序与VapeV4主程序大差不差,很多函数都是一样的,比如提权(SeDebugPrivilege),本地Socket监听,RenderingUI,检测Minecraft存活,Hwid,Login等等......

在注入后会建立Socket与客户端保持联系,这一点与V4也一样。

VapeLite与VapeV4不同的点在于,它不会检查(也无法检查)Minecraft是否被注入过,因为客户端被注入后没有和VapeV4客户端一样打开一个pipe供检查。

所以,我们只需要分析它的远程线程注入,拿到StubDll即可,其他无需分析。

InjectedStub - 注入的DLL

What's same

采用一样的方案,Hook WriteProcessMemory即可完整dump出VapeLite.dll。

VapeLite.dll中还是有"Vape Lite"这样特殊的字符串供检测,只要对java.exe内存全量扫描即可查出。

与VapeV4.dll不同的是,VapeLite.dll没有加壳也没有进行代码虚拟化,极大方便了我们的分析。

本人认为可以将VapeLite.dll与VapeV4.dll对比分析,毕竟这两个dll的大部分代码都相同,比如下面就是DllMain,这在VapeV4.dll中是完全虚拟化的。

通过分析我们可以得知,TCPPort依旧是从主程序传来(CreateRemoteThread),之后在ReflectiveLoader工作完毕后传入DllEntry的Reserved参数中。

随后创建线程,使用该Port作为线程参数值,传入新线程,从而传入DllMain。

DllMain中依旧采用JNI_GetCreatedJavaVMs获取当前VM。

GetForgeVersion

CustomClassLoader

这个函数是从 native 端构造 Java 类路径,然后通过自定义 ClassLoader 加载对应类,并返回其全局引用(jclass 或对象),并将引用缓存到结构体中以复用。

jobject __fastcall vapeClassLoader(struct_a1 *a1, JNIEnv *a2, const char *str)
{
  int v7; // r9d
  __int64 len; // r8
  __int64 v9; // rax
  char *v10; // rdx
  unsigned __int64 v11; // rcx
  __int64 v13; // rax
  char *v14; // rdx
  unsigned __int64 v15; // rax
  jstring (**p_NewStringUTF)(JNIEnv *, const char *); // rax
  va_list param_str; // rax
  jobject v18; // rax
  jobject v19; // rax
  jobject v20; // rcx
  jobject v21; // rbx
  jclass v22; // rax
  _BYTE *v23; // rdx
  jobject v24[2]; // [rsp+30h] [rbp-438h] BYREF
  char Buffer[1024]; // [rsp+40h] [rbp-428h] BYREF

  if ( !*&a1->gap0[8] )
    return 0LL;
  memset(Buffer, 0, sizeof(Buffer));
  vsprintf(Buffer, "%s", str);
  v7 = 0;
  len = 0LL;
  v9 = -1LL;
  do
    ++v9;                                       // strlen
  while ( Buffer[v9] );
  if ( v9 )
  {
    v10 = Buffer;
    do
    {
      if ( *v10 == '.' )                        // translate . -> /
        *v10 = '/';
      len = (len + 1);
      ++v10;
      v11 = -1LL;
      do
        ++v11;
      while ( Buffer[v11] );
    }
    while ( len < v11 );
  }
  if ( !a1->byte56 )
    goto LABEL_23;
  v13 = -1LL;
  do                                            // // strlen
    ++v13;
  while ( Buffer[v13] );
  if ( v13 )                                    // Translate / -> .
  {
    v14 = Buffer;
    do
    {
      if ( *v14 == '/' )
        *v14 = '.';
      ++v7;
      ++v14;
      v15 = -1LL;
      do
        ++v15;
      while ( Buffer[v15] );
    }
    while ( v7 < v15 );
    p_NewStringUTF = &(*a2)->NewStringUTF;
  }
  else
  {
LABEL_23:
    p_NewStringUTF = &(*a2)->NewStringUTF;
  }
  param_str = (*p_NewStringUTF)(a2, Buffer, len);
  v18 = JNI_CallObjectMethodV(a2, *&a1->gap0[8], *&a1->gap30[24], param_str);
  v19 = (*a2)->NewGlobalRef(a2, v18);
  v24[0] = v19;
  v20 = v19;
  v21 = v19;
  if ( v19 )
    goto LABEL_28;
  if ( (*a2)->ExceptionOccurred(a2) )
    (*a2)->ExceptionClear(a2);
  v22 = (*a2)->FindClass(a2, Buffer);
  v19 = (*a2)->NewGlobalRef(a2, v22);
  v24[0] = v19;
  v20 = v19;
  v21 = v19;
  if ( v19 )
  {
LABEL_28:
    v23 = *&a1->gap30[8];
    if ( v23 == *&a1->gap30[16] )
    {
      sub_180011B30(a1->gap30, v23, v24);
      return v21;
    }
    else
    {
      *v23 = v19;
      *&a1->gap30[8] += 8LL;
    }
  }
  return v20;
}

UpperClassFinder

如果是 Minecraft 类,走上面的ClassLoader,否则走FindClass。

jobject __fastcall upperClassFinder(__int64 a1, JNIEnv *a2, const char *a3)
{
  __int64 v6; // rdx
  __int64 v7; // rcx
  __int64 v8; // rbx
  unsigned __int64 v9; // rbx
  jobject result; // rax
  char *v11; // rdx
  __int64 v12; // rsi
  __int64 v13; // r14
  __int64 v14; // rdx
  __int64 v15; // rbx
  jobject **v16; // r9
  jobject **v17; // r11
  jobject *v18; // r10
  __int64 v19; // rcx
  __int64 v20; // rax
  char *v21; // r8
  int v22; // ecx
  char v23; // al
  size_t v24; // rdi
  __int64 v25; // rdx
  __int64 v26; // rcx
  unsigned __int64 v27; // rdi
  __int64 v28; // rax
  bool v29; // zf
  __int64 v30; // rax
  __int64 v31; // rdx
  char v32; // al
  __int64 v33; // rax
  __int64 v34; // rax
  unsigned __int64 v35; // rax
  __int64 v36; // rdx
  __int64 v37; // rcx
  unsigned __int64 v38; // rbx
  char Buffer[2048]; // [rsp+20h] [rbp-E0h] BYREF
  char Str[2048]; // [rsp+820h] [rbp+720h] BYREF

  if ( *(a1 + 8) && ((*(a1 + 96) - *(a1 + 88)) & 0xFFFFFFFFFFFFFFF8uLL) == 0 )
  {
    memset(Buffer, 0, sizeof(Buffer));
    if ( *a3 == 76 )
    {
      vsprintf(Buffer, "%s", a3 + 1);
      v8 = -1LL;
      do
        ++v8;
      while ( Buffer[v8] );
      v9 = v8 - 1;
      if ( v9 >= 0x800 )
        sub_18018EAB0(v7, v6);
      Buffer[v9] = 0;
    }
    else
    {
      vsprintf(Buffer, "%s", a3);
    }
    if ( strstr(Buffer, "net/minecraft") )
      return vapeClassLoader(a1, a2, Buffer);
    else
      return (*a2)->FindClass(a2, Buffer);
  }
  memset(Str, 0, sizeof(Str));
  v11 = "%s";
  if ( *a3 != 76 )
    v11 = "L%s;";
  vsprintf(Str, v11, a3);
  v12 = 0LL;
  v13 = 0LL;
  v15 = -1LL;
  if ( strstr(Str, "net/minecraft") || *(a1 + 33) && (strstr(Str, "netty") || strstr(Str, "lwjgl")) )
  {
    v16 = *(a1 + 88);
    v17 = *(a1 + 96);
    if ( v16 != v17 )
    {
      while ( 1 )
      {
        v18 = *v16;
        v19 = -1LL;
        v20 = (*v16 + 1);
        do
          ++v19;
        while ( *(v20 + v19) );
        if ( v19 )
        {
          v21 = &Str[-v20];
          do
          {
            v22 = v21[v20];
            v14 = *v20 - v22;
            if ( v14 )
              break;
            ++v20;
          }
          while ( v22 );
          if ( !v14 )
            break;
        }
        if ( ++v16 == v17 )
          goto LABEL_29;
      }
      v13 = *v18;
      if ( *v18 )
        return v13;
    }
  }
LABEL_29:
  v23 = Str[0];
  if ( Str[0] != 91 )
  {
LABEL_40:
    if ( v23 == 76 )
    {
LABEL_47:
      if ( !v13 )
      {
        memset(Buffer, 0, sizeof(Buffer));
        if ( *a3 == 76 )
        {
          vsprintf(Buffer, "%s", a3 + 1);
          do
            ++v15;
          while ( Buffer[v15] );
          v38 = v15 - 1;
          if ( v38 >= 0x800 )
            sub_18018EAB0(v37, v36);
          Buffer[v38] = 0;
        }
        else
        {
          vsprintf(Buffer, "%s", a3);
        }
        if ( strstr(Buffer, "net/minecraft") )
          return vapeClassLoader(a1, a2, Buffer);
        else
          return (*a2)->FindClass(a2, Buffer);
      }
      return v13;
    }
LABEL_41:
    Buffer[0] = 76;
    do
    {
      v32 = Str[v12];
      Buffer[++v12] = v32;
    }
    while ( v32 );
    v33 = -1LL;
    do
      ++v33;
    while ( Str[v33] );
    v34 = v33 + 1;
    Buffer[v34] = 59;
    v35 = v34 + 1;
    if ( v35 >= 0x400 )
      sub_18018EAB0(Str, v14);
    Buffer[v35] = 0;
    v13 = sub_180026130(a1, Buffer);
    goto LABEL_47;
  }
  if ( Str[1] != 76 )
    goto LABEL_41;
  strcpy(Buffer, Str);
  v24 = -1LL;
  do
    ++v24;
  while ( Str[v24] );
  memcpy(Buffer, &Str[1], v24);
  v27 = v24 - 2;
  if ( v27 >= 0x400 )
    sub_18018EAB0(v26, v25);
  Buffer[v27] = 0;
  Buffer[0] = 91;
  v28 = -1LL;
  do
    v29 = Buffer[++v28] == 0;
  while ( !v29 );
  Buffer[v28] = 59;
  v30 = -1LL;
  do
    v29 = Buffer[++v30] == 0;
  while ( !v29 );
  v31 = *(a1 + 40);
  Buffer[v30 + 1] = 48;
  result = vapeClassLoader(a1, *(v31 + 8), Buffer);
  v13 = result;
  if ( !result )
  {
    v23 = Str[0];
    goto LABEL_40;
  }
  return result;
}

注册 EventBus

Event是现代CheatClient或者mod的基本要素,用于在游戏特定时期来完成特定功能,Vape Lite兼容多版本,所以对于这里的操作有不同种类,下面我们简单分析一下ForgeVersion在26上下的操作。

ForgeVersion < 26

注入一个随机名称的类

InlineHook Lwjgl64.dll

我们可以看出,Display.getAvailableDisplayModes() 这个函数的处理流程在Lwjgl64的Native中,而VapeLite.dll采用InlineHook,使此函数的Native处理流程重定向到了自己的处理函数 lwjgl_getAvailableDisplayModes_Callback。

lwjgl_getAvailableDisplayModes_Callback

ForgeVersion >= 26

注入a.class

RegisterNative
  if ( gForgeVersion >= 26 )
  {
    v6[0] = "invoke";
    v6[1] = "(Lnet/minecraftforge/eventbus/api/Event;)V";
    v6[2] = sub_180101670;
    sub_180102790(*(a1 + 168), *(a1 + 160), v6, 1LL);
  }

其他操作(注册 Event, 获取基本类)

__int64 __fastcall sub_180100390(__int64 a1, JNIEnv *a2)
{
  _OWORD *v2; // rax
  _OWORD *v3; // rax
  _OWORD *v4; // rax
  _OWORD *v5; // rax
  _OWORD *v6; // rax
  int v7; // eax
  int v8; // eax
  int v9; // eax
  int v10; // eax
  int v11; // eax
  int v12; // eax
  _OWORD *v13; // rax
  _OWORD *v14; // rax
  _OWORD *v15; // rax
  _OWORD *v16; // rax
  int v17; // eax
  int v18; // eax
  int v19; // eax
  int v20; // eax
  __int64 v21; // rax
  _OWORD *v22; // rax
  _OWORD *v23; // rax
  _OWORD *v24; // rax
  _OWORD *v25; // rax
  int v26; // eax
  int v27; // eax
  int v28; // eax
  int v29; // eax
  struct_a1 *v30; // rax
  struct_a1 *v31; // rax
  struct_a1 *v32; // rax
  struct_a1 *v33; // rax
  struct_a1 *v34; // rax
  struct_a1 *v35; // rax
  struct_a1 *v36; // rax
  struct_a1 *v37; // rax
  struct_a1 *v38; // rax
  struct_a1 *v39; // rax
  struct_a1 *v40; // rax
  struct_a1 *v41; // rax
  struct_a1 *v42; // rax
  struct_a1 *v43; // rax
  struct_a1 *v44; // rax
  int v45; // eax
  _OWORD *v46; // rax
  _OWORD *v47; // rax
  _OWORD *v48; // rax
  _OWORD *v49; // rax
  struct_a1 *v50; // rax
  int v51; // eax
  __int64 v52; // rax
  _OWORD *v53; // rax
  _OWORD *v54; // rax
  _OWORD *v55; // rax
  _OWORD *v56; // rax
  struct_a1 *v57; // rax
  int v58; // eax
  jfieldID FieldId; // rax
  jobject v61; // [rsp+30h] [rbp-18h]
  jobject v62; // [rsp+30h] [rbp-18h]
  jobject v63; // [rsp+30h] [rbp-18h]

  *a1 = off_1801DCA48;
  *a1 = off_1801DCA38;
  sub_180102590(a1 + 176);
  qword_1802D72F0 = sub_180171C00();
  *(a1 + 168) = a2;
  sub_180171C00();
  gForgeVersion = getForgeVersion();
  if ( gForgeVersion == 13 )
    dword_1802D7310 = 3;
  else
    dword_1802D7310 = 1;
  if ( gForgeVersion == 13 )
  {
    v2 = VapeClassLoader();
    *(a1 + 200) = VapeClassFinder(v2, "Lcpw/mods/fml/common/eventhandler/Event;");
    v3 = VapeClassLoader();
    *(a1 + 208) = VapeClassFinder(v3, "Lcpw/mods/fml/common/eventhandler/ListenerList;");
    v4 = VapeClassLoader();
    *(a1 + 216) = VapeClassFinder(v4, "Lcpw/mods/fml/common/eventhandler/EventPriority;");
    v5 = VapeClassLoader();
    *(a1 + 272) = VapeClassFinder(v5, "Lcpw/mods/fml/common/eventhandler/ListenerList$ListenerListInst;");
    v6 = VapeClassLoader();
    *(a1 + 224) = VapeClassFinder(v6, "Lcpw/mods/fml/common/eventhandler/IEventListener;");
    v7 = VapeClassLoader();
    *(a1 + 240) = sub_180026910(v7, *(a1 + 200), "getListenerList", "()Lcpw/mods/fml/common/eventhandler/ListenerList;");
    v8 = VapeClassLoader();
    *(a1 + 152) = sub_180026910(v8, *(a1 + 200), "setCanceled", "(Z)V");
    v9 = VapeClassLoader();
    *(a1 + 248) = sub_180026910(
                    v9,
                    *(a1 + 208),
                    "register",
                    "(ILcpw/mods/fml/common/eventhandler/EventPriority;Lcpw/mods/fml/common/eventhandler/IEventListener;)V");
    v10 = VapeClassLoader();
    *(a1 + 256) = sub_180026910(v10, *(a1 + 208), "unregister", "(ILcpw/mods/fml/common/eventhandler/IEventListener;)V");
    v11 = VapeClassLoader();
    *(a1 + 288) = sub_180026910(
                    v11,
                    *(a1 + 208),
                    "getListeners",
                    "(I)[Lcpw/mods/fml/common/eventhandler/IEventListener;");
    v12 = VapeClassLoader();
    *(a1 + 232) = sub_180026F90(v12, *(a1 + 216), "HIGHEST", "Lcpw/mods/fml/common/eventhandler/EventPriority;", 0LL);
  }
  else
  {
    if ( gForgeVersion < 26 )
    {
      v22 = VapeClassLoader();
      *(a1 + 200) = VapeClassFinder(v22, "Lnet/minecraftforge/fml/common/eventhandler/Event;");
      v23 = VapeClassLoader();
      *(a1 + 208) = VapeClassFinder(v23, "Lnet/minecraftforge/fml/common/eventhandler/ListenerList;");
      v24 = VapeClassLoader();
      *(a1 + 216) = VapeClassFinder(v24, "Lnet/minecraftforge/fml/common/eventhandler/EventPriority;");
      v25 = VapeClassLoader();
      *(a1 + 272) = VapeClassFinder(v25, "Lnet/minecraftforge/fml/common/eventhandler/ListenerList$ListenerListInst;");
      *(a1 + 240) = JNI_GetMethodID(
                      a2,
                      *(a1 + 200),
                      "getListenerList",
                      "()Lnet/minecraftforge/fml/common/eventhandler/ListenerList;");
      v26 = VapeClassLoader();
      *(a1 + 248) = sub_180026910(
                      v26,
                      *(a1 + 208),
                      "register",
                      "(ILnet/minecraftforge/fml/common/eventhandler/EventPriority;Lnet/minecraftforge/fml/common/eventha"
                      "ndler/IEventListener;)V");
      v27 = VapeClassLoader();
      *(a1 + 256) = sub_180026910(
                      v27,
                      *(a1 + 208),
                      "unregister",
                      "(ILnet/minecraftforge/fml/common/eventhandler/IEventListener;)V");
      v28 = VapeClassLoader();
      *(a1 + 288) = sub_180026910(
                      v28,
                      *(a1 + 208),
                      "getListeners",
                      "(I)[Lnet/minecraftforge/fml/common/eventhandler/IEventListener;");
      v29 = VapeClassLoader();
      v21 = sub_180026F90(
              v29,
              *(a1 + 216),
              "HIGHEST",
              "Lnet/minecraftforge/fml/common/eventhandler/EventPriority;",
              0LL);
    }
    else
    {
      v13 = VapeClassLoader();
      *(a1 + 200) = VapeClassFinder(v13, "Lnet/minecraftforge/eventbus/api/Event;");
      v14 = VapeClassLoader();
      *(a1 + 208) = VapeClassFinder(v14, "Lnet/minecraftforge/eventbus/ListenerList;");
      v15 = VapeClassLoader();
      *(a1 + 216) = VapeClassFinder(v15, "Lnet/minecraftforge/eventbus/api/EventPriority;");
      v16 = VapeClassLoader();
      *(a1 + 272) = VapeClassFinder(v16, "Lnet/minecraftforge/eventbus/ListenerList$ListenerListInst;");
      *(a1 + 240) = JNI_GetMethodID(a2, *(a1 + 200), "getListenerList", "()Lnet/minecraftforge/eventbus/ListenerList;");
      v17 = VapeClassLoader();
      *(a1 + 248) = sub_180026910(
                      v17,
                      *(a1 + 208),
                      "register",
                      "(ILnet/minecraftforge/eventbus/api/EventPriority;Lnet/minecraftforge/eventbus/api/IEventListener;)V");
      v18 = VapeClassLoader();
      *(a1 + 256) = sub_180026910(
                      v18,
                      *(a1 + 208),
                      "unregister",
                      "(ILnet/minecraftforge/eventbus/api/IEventListener;)V");
      v19 = VapeClassLoader();
      *(a1 + 288) = sub_180026910(
                      v19,
                      *(a1 + 208),
                      "getListeners",
                      "(I)[Lnet/minecraftforge/eventbus/api/IEventListener;");
      v20 = VapeClassLoader();
      v21 = sub_180026F90(v20, *(a1 + 216), "HIGHEST", "Lnet/minecraftforge/eventbus/api/EventPriority;", 0LL);
    }
    *(a1 + 232) = v21;
    *(a1 + 152) = JNI_GetMethodID(a2, *(a1 + 200), "setCanceled", "(Z)V");
  }
  if ( gForgeVersion < 26 )
  {
    v30 = VapeClassLoader();
    *(a1 + 8) = vapeClassLoader(v30);
  }
  if ( gForgeVersion < 35 )
  {
    v33 = VapeClassLoader();
    *(a1 + 32) = vapeClassLoader(v33);
  }
  else
  {
    v31 = VapeClassLoader();
    *(a1 + 32) = vapeClassLoader(v31);
    v32 = VapeClassLoader();
    *(a1 + 72) = vapeClassLoader(v32);
  }
  v34 = VapeClassLoader();
  *(a1 + 16) = vapeClassLoader(v34);
  v35 = VapeClassLoader();
  *(a1 + 24) = vapeClassLoader(v35);
  v36 = VapeClassLoader();
  *(a1 + 64) = vapeClassLoader(v36);
  v37 = VapeClassLoader();
  *(a1 + 80) = vapeClassLoader(v37);
  v38 = VapeClassLoader();
  *(a1 + 88) = vapeClassLoader(v38);
  v39 = VapeClassLoader();
  *(a1 + 96) = vapeClassLoader(v39);
  *(a1 + 104) = JNI_GetFieldId(
                  a2,
                  *(a1 + 80),
                  "type",
                  "Lnet/minecraftforge/client/event/RenderGameOverlayEvent$ElementType;");
  *(a1 + 112) = JNI_GetStaticFieldID(a2);
  if ( gForgeVersion < 26 )
    fieldID = JNI_GetFieldId(a2, *(a1 + 16), "entityLiving", "Lnet/minecraft/entity/EntityLivingBase;");
  else
    fieldID = JNI_GetFieldId(a2, *(a1 + 16), "entityLiving", "Lnet/minecraft/entity/LivingEntity;");
  if ( gForgeVersion == 13 )
  {
    v40 = VapeClassLoader();
    v61 = vapeClassLoader(v40);
    v41 = VapeClassLoader();
    *(a1 + 48) = vapeClassLoader(v41);
    v42 = VapeClassLoader();
    *(a1 + 40) = vapeClassLoader(v42);
    v43 = VapeClassLoader();
    *(a1 + 56) = vapeClassLoader(v43);
    v44 = VapeClassLoader();
    *(a1 + 120) = vapeClassLoader(v44);
    *(a1 + 136) = JNI_GetFieldId(a2, v61, "phase", "Lcpw/mods/fml/common/gameevent/TickEvent$Phase;");
    *(a1 + 144) = JNI_GetStaticFieldID(a2);
    v45 = VapeClassLoader();
    *(a1 + 280) = sub_180026F90(
                    v45,
                    *(a1 + 208),
                    "lists",
                    "[Lcpw/mods/fml/common/eventhandler/ListenerList$ListenerListInst;",
                    0LL);
  }
  else
  {
    if ( gForgeVersion < 26 )
    {
      v53 = VapeClassLoader();
      v63 = VapeClassFinder(v53, "net/minecraftforge/fml/common/gameevent/TickEvent");
      v54 = VapeClassLoader();
      *(a1 + 48) = VapeClassFinder(v54, "net/minecraftforge/fml/common/gameevent/TickEvent$RenderTickEvent");
      v55 = VapeClassLoader();
      *(a1 + 40) = VapeClassFinder(v55, "net/minecraftforge/fml/common/gameevent/TickEvent$PlayerTickEvent");
      v56 = VapeClassLoader();
      *(a1 + 56) = VapeClassFinder(v56, "net/minecraftforge/fml/common/gameevent/TickEvent$ClientTickEvent");
      v57 = VapeClassLoader();
      *(a1 + 120) = vapeClassLoader(v57);
      *(a1 + 136) = JNI_GetFieldId(a2, v63, "phase", "Lnet/minecraftforge/fml/common/gameevent/TickEvent$Phase;");
      *(a1 + 144) = JNI_GetStaticFieldID(a2);
      v58 = VapeClassLoader();
      v52 = sub_180026F90(
              v58,
              *(a1 + 208),
              "lists",
              "[Lnet/minecraftforge/fml/common/eventhandler/ListenerList$ListenerListInst;",
              0LL);
    }
    else
    {
      v46 = VapeClassLoader();
      v62 = VapeClassFinder(v46, "net/minecraftforge/event/TickEvent");
      v47 = VapeClassLoader();
      *(a1 + 48) = VapeClassFinder(v47, "net/minecraftforge/event/TickEvent$RenderTickEvent");
      v48 = VapeClassLoader();
      *(a1 + 40) = VapeClassFinder(v48, "net/minecraftforge/event/TickEvent$PlayerTickEvent");
      v49 = VapeClassLoader();
      *(a1 + 56) = VapeClassFinder(v49, "net/minecraftforge/event/TickEvent$ClientTickEvent");
      v50 = VapeClassLoader();
      *(a1 + 120) = vapeClassLoader(v50);
      *(a1 + 136) = JNI_GetFieldId(a2, v62, "phase", "Lnet/minecraftforge/event/TickEvent$Phase;");
      *(a1 + 144) = JNI_GetStaticFieldID(a2);
      v51 = VapeClassLoader();
      v52 = sub_180026F90(
              v51,
              *(a1 + 208),
              "lists",
              "[Lnet/minecraftforge/eventbus/ListenerList$ListenerListInst;",
              0LL);
    }
    *(a1 + 280) = v52;
  }
  if ( gForgeVersion < 26 )
    FieldId = JNI_GetFieldId(a2, *(a1 + 40), "player", "Lnet/minecraft/entity/player/EntityPlayer;");
  else
    FieldId = JNI_GetFieldId(a2, *(a1 + 40), "player", "Lnet/minecraft/entity/player/PlayerEntity;");
  *(a1 + 128) = FieldId;
  return a1;
}

EventHandler

EventHandler由Invoke调用而来,可以发现他把第一个jobject解引用了,一般情况下,这是非法操作,但是Vape通过自己布局Object,使得类偏移为8的地方放置了Dispatcher。

__int64 __fastcall Java_p000_C000a_invoke(JNIEnv *a1, __int64 a2, jobject Event)
{
  __int64 result; // rax
  __int64 (__fastcall **v4)(JNIEnv *, jobject); // rax
  unsigned __int64 v5; // [rsp+28h] [rbp-20h] BYREF

  v5 = *(deRef(Event) + 8);
  result = BstSearch::contains(&bst_Tree, &v5);
  if ( result )
  {
    v4 = Bst::FindAndIns(&bst_Tree, &v5);
    return (*v4)(a1, Event);
  }
  return result;
}

典型的事件分发流程。

主功能

Vape Lite的所有功能的操作都在主程序,主程序与StubDll通信然后StubDll进行相应的操作来做到,另外,Vape Lite还支持非Forge客户端的劫持,这个笔者有时间会继续深入研究。

检测 & 防止

检测方案

检查类型

Vape V4

Vape Lite

字符串特征检查

✔️

✔️

pipe检查

✔️

.vapeclient 文件夹

当用户同意缓存时

Java 类扫描

✔️

getAvailableDisplayModes

Hook检查

✔️

防止方案

检查类型

Vape V4

Vape Lite

字符串特征检查

✔️

✔️

屏幕截图

当用户开启视觉功能时

当用户开启视觉功能时

进程名扫描 & 分析

✔️

.vapeclient 文件夹

当用户同意缓存时

Hook JavaAPI

✔️

✔️

内存隐藏模块检查

✔️

✔️

Java 类扫描

✔️

驱动保护 Java.exe

✔️

✔️

相关附件

Vape V4

附件包括vape_v4.exe(主程序),vape_v4.dll(Dumped Stub)与 vape.jar (通过DefineClass动态注册的客户端核心)。

下载: https://sts.lanzoue.com/i4fHf312btif 密码: a4o4

仅供学习参考使用,请在下载后24h内自行删除。