Giter Club home page Giter Club logo

txfinal's Introduction

决赛 writeup

文件名 作用
PatchDriver.sys patch释放和vad断链 flag
HookPatch.dll hook 方式 绘制flag和截图
print.exe 输出虚拟机操作码 修复操作码 输出正确坐标
dump.mem shellcode ida分析文件
2022GameSafeRace.sys.i64 驱动 ida分析文件
Patch.zip vs项目压缩包
screenshot.dll 截图dll home 截图保存到d:\dwm.jpg
HookPatch.dll patchdll 注入可以看到flag
flag.jpg 利用室友电脑所截的图
Table.h 生成并加密回去的opcode

Patch

方案一

hook并调用坐标绘制

搜索 比赛驱动的hook

然后我再hook

注入压缩包中的HookPatch.dll 可以看到效果

	FILE* file;
	AllocConsole();
	freopen_s(&file, "CONIN$", "r", stdin);
	freopen_s(&file, "CONOUT$", "w", stdout);
	uint64_t hook = 0;
	while (true)
	{
		hook = FindPattern("dxgi.dll", "68 ?? ?? ?? ?? C7 44 24 04 ?? ?? ?? ??");
		if (hook)
			break;
		Sleep(100);
	}
flag f[42];
uint8_t* draw_rect = 0;
uint8_t* draw_orig = 0;
__int64 __fastcall sub_420(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, __int64 a7)
{
	f[0] = { 50 , 50, 0x130bd0 , 0xf814b4 };
	f[1] = { 50 , 122, 0x1bcd69 , 0xe9bdc5 };
	f[2] = { 50 , 194, 0xd91997 , 0x4f7363 };
	f[3] = { 50 , 266, 0xe82b18 , 0x28ec24 };
	f[4] = { 50 , 338, 0x391faa , 0x22ae2e };
	f[5] = { 50 , 410, 0xd77de2 , 0x2f62e };
	f[6] = { 122 , 266, 0x71150 , 0x1894d4 };
	f[7] = { 194 , 266, 0xc42e8b , 0xeb1f47 };
	f[8] = { 266 , 266, 0x34cf2b , 0x534f3f };
	f[9] = { 122 , 122, 0xd9e5f1 , 0xe9d505 };
	f[10] = { 194 , 194, 0xc42d8b , 0x38f0f };
	f[11] = { 770 , 50, 0xeabf17 , 0x8f7323 };
	f[12] = { 698 , 122, 0xc42d8b , 0x532fbf };
	f[13] = { 626 , 194, 0xd717af , 0x37cb9b };
	f[14] = { 554 , 266, 0xc460e9 , 0x314ddd };
	f[15] = { 482 , 338, 0xc7a989 , 0x11edbd };
	f[16] = { 554 , 338, 0xab7100 , 0xf0747c };
	f[17] = { 626 , 338, 0xc409a9 , 0xe12d6d };
	f[18] = { 842 , 50, 0xd77e8b , 0x7bfff7 };
	f[19] = { 914 , 50, 0xd9ad01 , 0x4985c5 };
	f[20] = { 986 , 50, 0x39e156 , 0xf6c25a };
	f[21] = { 842 , 122, 0x13207c , 0x7438b8 };
	f[22] = { 914 , 194, 0xc9140b , 0xf3af5f };
	f[23] = { 986 , 266, 0x53071f , 0x779bfb };
	f[24] = { 1058 , 338, 0xd71106 , 0x5ee272 };
	f[25] = { 1130 , 338, 0xeb60a1 , 0x11551d };
	f[26] = { 1202 , 338, 0xeb67cd , 0xc5c9c9 };
	f[27] = { 1274 , 338, 0xd71161 , 0x1752d };
	f[28] = { 1130 , 50, 0x677611 , 0x41a58d };
	f[29] = { 1202 , 50, 0x40173d , 0x95f9d9 };
	f[30] = { 1274 , 50, 0xd77661 , 0x61b54d };
	f[31] = { 1346 , 50, 0xefff9a , 0xc27eee };
	f[32] = { 1202 , 122, 0xc404eb , 0xeb3fc7 };
	f[33] = { 1274 , 194, 0xd7c6ef , 0xdf9b53 };
	f[34] = { 1346 , 194, 0xd7701f , 0x171b1b };
	f[35] = { 1418 , 194, 0xd71171 , 0x91e53d };
	f[36] = { 1490 , 194, 0x3906ab , 0x138f3f };
	f[37] = { 1346 , 266, 0x96663 , 0x83f72f };
	f[38] = { 1418 , 338, 0x732157 , 0x47638b };
	f[39] = { 1490 , 338, 0x353730 , 0x587414 };
	f[40] = { 1562 , 338, 0x6257a9 , 0x69fdc5 };
	f[41] = { 1634 , 338, 0xd777af , 0xb7cb1b };



	for (auto& data : f)
	{
		
		call_invoke(draw_rect, data.x, data.y, data.k1, data.k2, 0xFF2DDBE7, a3, a4, a5, a6, a7);
		
		//reinterpret_cast<uint64_t(*)(int, int, int, int, int, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t)>(draw_rect)
		//    (data.x, data.y, data.k1, data.k2, 0xFFFFFF00, a3, a4, a5, a6, a7);
	}
	return 0;

方案二

通过虚拟机模拟,得到绘制坐标信息

再通过std::vector<uint32_t> VM::OutVituralOpCodeTable(const std::vector& opcodes)

生成新的opcode

利用驱动loadimg 回调

patch 目标驱动

由于是通过loadimg进行patch 所以PatchDriver.sys 需要在比赛驱动之前加载

加载PatchDriver.sys 后加载比赛驱动在运行2022游戏安全技术竞赛决赛.exe 可以看到flag

注入screenshot.dll 按home 即可截图 截图文件在 d:\dwm.jpg

EE2362FC Reg[0],Reg[1] <- Draw(50,50,130bd0,f814b4)
EE2362FC Reg[0],Reg[1] <- Draw(50,122,1bcd69,e9bdc5)
EE2362FC Reg[0],Reg[1] <- Draw(50,194,d91997,4f7363)
EE2362FC Reg[0],Reg[1] <- Draw(50,266,e82b18,28ec24)
EE2362FC Reg[0],Reg[1] <- Draw(50,338,391faa,22ae2e)
EE2362FC Reg[0],Reg[1] <- Draw(50,410,d77de2,2f62e)
EE2362FC Reg[0],Reg[1] <- Draw(122,266,71150,1894d4)
EE2362FC Reg[0],Reg[1] <- Draw(194,266,c42e8b,eb1f47)
EE2362FC Reg[0],Reg[1] <- Draw(266,266,34cf2b,534f3f)
EE2362FC Reg[0],Reg[1] <- Draw(122,122,d9e5f1,e9d505)
EE2362FC Reg[0],Reg[1] <- Draw(194,194,c42d8b,38f0f)
EE2362FC Reg[0],Reg[1] <- Draw(770,50,eabf17,8f7323)
EE2362FC Reg[0],Reg[1] <- Draw(698,122,c42d8b,532fbf)
EE2362FC Reg[0],Reg[1] <- Draw(626,194,d717af,37cb9b)
EE2362FC Reg[0],Reg[1] <- Draw(554,266,c460e9,314ddd)
EE2362FC Reg[0],Reg[1] <- Draw(482,338,c7a989,11edbd)
EE2362FC Reg[0],Reg[1] <- Draw(554,338,ab7100,f0747c)
EE2362FC Reg[0],Reg[1] <- Draw(626,338,c409a9,e12d6d)
EE2362FC Reg[0],Reg[1] <- Draw(842,50,d77e8b,7bfff7)
EE2362FC Reg[0],Reg[1] <- Draw(914,50,d9ad01,4985c5)
EE2362FC Reg[0],Reg[1] <- Draw(986,50,39e156,f6c25a)
EE2362FC Reg[0],Reg[1] <- Draw(842,122,13207c,7438b8)
EE2362FC Reg[0],Reg[1] <- Draw(914,194,c9140b,f3af5f)
EE2362FC Reg[0],Reg[1] <- Draw(986,266,53071f,779bfb)
EE2362FC Reg[0],Reg[1] <- Draw(1058,338,d71106,5ee272)
EE2362FC Reg[0],Reg[1] <- Draw(1130,338,eb60a1,11551d)
EE2362FC Reg[0],Reg[1] <- Draw(1202,338,eb67cd,c5c9c9)
EE2362FC Reg[0],Reg[1] <- Draw(1274,338,d71161,1752d)
EE2362FC Reg[0],Reg[1] <- Draw(1130,50,677611,41a58d)
EE2362FC Reg[0],Reg[1] <- Draw(1202,50,40173d,95f9d9)
EE2362FC Reg[0],Reg[1] <- Draw(1274,50,d77661,61b54d)
EE2362FC Reg[0],Reg[1] <- Draw(1346,50,efff9a,c27eee)
EE2362FC Reg[0],Reg[1] <- Draw(1202,122,c404eb,eb3fc7)
EE2362FC Reg[0],Reg[1] <- Draw(1274,194,d7c6ef,df9b53)
EE2362FC Reg[0],Reg[1] <- Draw(1346,194,d7701f,171b1b)
EE2362FC Reg[0],Reg[1] <- Draw(1418,194,d71171,91e53d)
EE2362FC Reg[0],Reg[1] <- Draw(1490,194,3906ab,138f3f)
EE2362FC Reg[0],Reg[1] <- Draw(1346,266,96663,83f72f)
EE2362FC Reg[0],Reg[1] <- Draw(1418,338,732157,47638b)
EE2362FC Reg[0],Reg[1] <- Draw(1490,338,353730,587414)
EE2362FC Reg[0],Reg[1] <- Draw(1562,338,6257a9,69fdc5)
EE2362FC Reg[0],Reg[1] <- Draw(1634,338,d777af,b7cb1b)
VOID LoadImageNotify(
	_In_ PUNICODE_STRING FullImageName,
	_In_ HANDLE ProcessId,
	_In_ PIMAGE_INFO ImageInfo
)
{
	if (FullImageName != nullptr && MmIsAddressValid(FullImageName))
	{
		if (ProcessId == 0) // 是否是驱动
		{
			auto ImageName = FullImageName->Buffer;
			if (wcsstr(ImageName, L"2022GameSafeRace.sys"))
			{
				auto PatchFree = reinterpret_cast<uint8_t*>(ImageInfo->ImageBase) + 0x18a4;
				auto JmpAddress = reinterpret_cast<uint8_t*>(ImageInfo->ImageBase) + 0x19ea;
				char jmp[] = {
					0xe9,0x00,0x00,0x00,0x00
				};
				*(uint32_t*)(jmp + 1) = (ULONG64)(JmpAddress - PatchFree - 5);
				// patch free
				MdlCopyMemory(PatchFree, &jmp, sizeof(jmp));
				// patch vad断链
				PatchFree = reinterpret_cast<uint8_t*>(ImageInfo->ImageBase) + 0x1aae;
				JmpAddress = reinterpret_cast<uint8_t*>(ImageInfo->ImageBase) + 0x1ac9;
				*(uint32_t*)(jmp + 1) = (ULONG64)(JmpAddress - PatchFree - 5);

				MdlCopyMemory(PatchFree, &jmp, sizeof(jmp));

				MdlCopyMemory(PatchFree, &jmp, sizeof(jmp));
				//patch表
				PatchFree = reinterpret_cast<uint8_t*>(ImageInfo->ImageBase) + 0x4030;

				MdlCopyMemory(PatchFree, Table, sizeof(Table));



			}
		}
	}
}

驱动分析

通讯

注册回调

NTSTATUS __fastcall sub_140001438(void *a1, BOOLEAN a2)
{
  SYSTEM_FIRMWARE_TABLE_HANDLER SystemInformation; // [rsp+20h] [rbp-28h] BYREF

  SystemInformation.DriverObject = a1;
  SystemInformation.Register = a2;
  SystemInformation.FirmwareTableHandler = (PFNFTH)sub_1400013E0;
  SystemInformation.ProviderSignature = 0x52414E44;
  return ZwSetSystemInformation(SystemRegisterFirmwareTableInformationHandler, &SystemInformation, 0x18ui64);
}
__int64 __fastcall sub_140003530(PVOID Parameter)
{
  HANDLE ProcessHeap; // rax
  char *v2; // rdx
  __int64 result; // rax
  ULONG ReturnLength; // [rsp+38h] [rbp+10h] BYREF

  ProcessHeap = GetProcessHeap();
  v2 = (char *)HeapAlloc(ProcessHeap, 8u, 0x28ui64);
  result = 0i64;
  *(_OWORD *)v2 = 0i64;
  *((_OWORD *)v2 + 1) = 0i64;
  *((_QWORD *)v2 + 4) = 0i64;
  if ( v2 )
  {
    *((_DWORD *)v2 + 2) = 0;
    *((_DWORD *)v2 + 1) = 1;
    *(_DWORD *)v2 = 1380011588;
    *((_DWORD *)v2 + 3) = 20;
    *(_QWORD *)(v2 + 20) = 8193i64;
    *((_QWORD *)v2 + 4) = D3DCompile;
    ReturnLength = 40;
    NtQuerySystemInformation(SystemFirmwareTableInformation, v2, 0x28u, &ReturnLength);
    return 0i64;
  }
  return result;
}

获取DWM PEPROCESS

循环遍历进程名有DWM的进程

起始Processid 为 0x100000

每次循环减4

PEPROCESS GetDwmProcess()//0x140001318
{
  PEPROCESS v0; // rdi
  unsigned int ProcessId; // esi
  void *ProcessImageFileName; // rbx
  void *ProcessPeb; // rbx
  struct _KAPC_STATE ApcState; // [rsp+20h] [rbp-60h] BYREF
  int SubStr; // [rsp+A0h] [rbp+20h] BYREF
  PEPROCESS Process; // [rsp+A8h] [rbp+28h] BYREF

  v0 = 0i64;
  ProcessId = 0x100000;
  while ( 1 )
  {
    if ( PsLookupProcessByProcessId((HANDLE)ProcessId, &Process) < 0 )
      goto LABEL_7;
    ObfDereferenceObject(Process);
    ProcessImageFileName = (void *)PsGetProcessImageFileName(Process);
    if ( !MmIsAddressValid(ProcessImageFileName) )
      goto LABEL_7;
    SubStr = 'mwd';
    if ( !strstr((const char *)ProcessImageFileName, (const char *)&SubStr) )
      goto LABEL_7;
    ProcessPeb = (void *)PsGetProcessPeb(Process);
    KeStackAttachProcess(Process, &ApcState);
    if ( MmIsAddressValid(ProcessPeb) )
      break;
    KeUnstackDetachProcess(&ApcState);
LABEL_7:
    ProcessId -= 4;
    if ( ProcessId <= 8 )
      return v0;
  }
  v0 = Process;
  KeUnstackDetachProcess(&ApcState);
  return v0;
}

注入shellcode

大概流程,获取DWM EPROCESS

获取 D3DCompile 地址

搜索内存 获取 CDXGISwapChain::PresentMultiplaneOverlay

申请内存 复制shellcodeVmOpcodeTable 到DWM中 并解密

HookMem = CDXGISwapChain::PresentMultiplaneOverlay 头部字节 加上

68 00006F99           - push 0000000000000000 { 0 }
C7 44 24 04 00000000  - mov [rsp+04],00000000 { 0 }
C3                    - ret 

= 跳回 PresentMultiplaneOverlay

hook CDXGISwapChain::PresentMultiplaneOverlay 跳到shellcode + 860

v31 = PresentMultiplaneOverlay(v43, a2, v49, a4, v72, a5, v71);

sub_860+D18 Address:0x1578 Offset:0x1578

这里执行 hookmem

延迟5秒恢复hook

延迟15秒释放内存

获取模块

ProcessId = PsGetProcessId(DwmProcess);
GetModuleHandle(ProcessId, &Handle, "D3DCOMPILER_47.dll");// 从Ldr链里获取模块地址
KeStackAttachProcess(Dwm, &ApcState);       // 附加DWM
if ( Handle )                               // 如果模块存在
    D3DCompile = GetProAddress((__int64)Handle, (__int64)"D3DCompile");// 获取函数D3DCompile地址
KeUnstackDetachProcess(&ApcState);          // 解除附加
Handle = 0i64;
v25 = 0i64;
GetModuleHandle(ProcessId, &Handle, "dxgi.dll");// 获取dxgi模块地址

查找PresentMultiplaneOverlay

 v5 = (char *)Handle;
    if ( Handle )
    {
      v6 = (char *)Handle;
      for ( i = Handle < (char *)Handle + v25; i; i = v6 < (char *)Handle + v25 )
      {
        if ( *(_QWORD *)v6 == qword_140004000 && *((_QWORD *)v6 + 1) == qword_140004008 && v6[0x10] == byte_140004010 )// 搜索特征码 PresentMultiplaneOverlay
        {
          PresentMultiplaneOverlay = v6;
          break;
        }
        ++v6;
      }
    }
    if ( unk_14000712C == 17134 && Handle )     // 如果为1803
    {
      v8 = (char *)Handle + v25;
      while ( v5 < v8 )
      {
        if ( !memcmp(v5, &unk_140004018, 0x15ui64) )// 搜索特征码
        {
          PresentMultiplaneOverlay = v5;
          break;
        }
        ++v5;
      }
    }

申请内存 并 copy Shellcode

  KeStackAttachProcess(Dwm, &ApcState);
      ZwAllocateVirtualMemory((HANDLE)0xFFFFFFFFFFFFFFFFi64, &BaseAddress, 0i64, &RegionSize, 0x1000u, 0x40u);// 申请shellcode 内存
      ZwAllocateVirtualMemory((HANDLE)0xFFFFFFFFFFFFFFFFi64, &HookMem, 0i64, &v23, 0x1000u, 0x40u);// hook内存?
      if ( BaseAddress && HookMem )
      {
        memcpy_s(BaseAddress, 0x30BAui64, dword_140005A00, 0x16E6ui64);// 复制shellcode 到申请的内存中
        v9 = 0;
        v10 = 0i64;
        do
        {
          ++v9;
          *((_BYTE *)BaseAddress + v10++) ^= 0xC3u;
        }
        while ( v9 < 0x16E6 );                  // 解密shellcode
        memcpy_s((char *)BaseAddress + 0x16E6, 0x19D4ui64, dword_140004030, 0x19C4ui64);// 复制VmOpcodeTable到申请的内存中
        v11 = 0;
        v12 = 0i64;
        do
        {
          ++v11;
          *((_BYTE *)BaseAddress + v12 + 0x16E6) ^= 0xCCu;// 解密 VmOpcodeTable
          ++v12;
        }
        while ( v11 < 0x19C4 );
        *(_QWORD *)((char *)BaseAddress + 0x30AA) = D3DCompile;
        *(_QWORD *)((char *)BaseAddress + 0x30B2) = HookMem;
        *(_DWORD *)((char *)BaseAddress + dword_1400059F4) = 0x30A6 - dword_1400059F4;
        *(_DWORD *)((char *)BaseAddress + dword_1400059F8) = 0x30AE - dword_1400059F8;
        *(_DWORD *)((char *)BaseAddress + dword_1400070EC) = 0x671;
        *(_DWORD *)((char *)BaseAddress + dword_1400070E8) = 0x16E2 - dword_1400070E8;
        memcpy_s(HookMem, 14ui64, &loc_1400070F8, 14ui64);// PresentMultiplaneOverlay 头部字节码
        v13 = (char *)HookMem;
        *(_DWORD *)((char *)HookMem + 15) = (_DWORD)PresentMultiplaneOverlay + 14;
        *(_DWORD *)(v13 + 0x17) = ((unsigned __int64)PresentMultiplaneOverlay + 14) >> 32;
        v13[14] = 0x68;
        *(_DWORD *)(v13 + 0x13) = 0x42444C7;
        v13[27] = 0xC3;

Hook PresentMultiplaneOverlay

利用MDL 强行写入shellcode 到PresentMultiplaneOverlay

Hook shellcode 大概

push 00000000 //push 低32位
mov [rsp+04] //mov 高32位
ret //jmp [rsp] pop
KeUnstackDetachProcess(&ApcState);
KeStackAttachProcess(Dwm, &ApcState);
if ( BaseAddress && HookMem )
{
    if ( MmIsAddressValid(PresentMultiplaneOverlay) )
    {
        Mdl = IoAllocateMdl(PresentMultiplaneOverlay, 0x100u, 0, 0, 0i64);
        MmProbeAndLockPages(Mdl, 1, IoReadAccess);
        v15 = (char *)MmMapLockedPagesSpecifyCache(Mdl, 0, MmNonCached, 0i64, 0, 0x10u);// hook
        if ( v15 )
        {   // 68 00000000           - push 00000000 { 0 }
            // C7 44 24 04 00000000  - mov [rsp+04],00000000 { 0 }
            // C3                    - ret 
            // shellcode
            v16 = (char *)BaseAddress + dword_1400070F0;// sub_860,各种初始化
            *(_DWORD *)(v15 + 1) = (_DWORD)v16;
            *(_DWORD *)(v15 + 9) = HIDWORD(v16);// 往里面写数据
            *v15 = 0x68;                        // push shellcode sub_860
            *(_DWORD *)(v15 + 5) = 69485767;    // mov [rsp+04],00000000
            v15[13] = 0xC3;                     // ret
        }
        MmUnmapLockedPages(v15, Mdl);
        MmUnlockPages(Mdl);
        IoFreeMdl(Mdl);
    }

VAD断链?

直接patch吧 一看就知道啥东西

没仔细看导致我minhook失败调我半天

v27[0] = (__int64)BaseAddress;
v29 = 0;
v27[1] = 0x30BAi64;
v28 = (unsigned int)PsGetProcessId(Dwm);
sub_140001A84((__int64)v27);

延迟5秒 并恢复hook

延迟5秒恢复PresentMultiplaneOverlay 的hook

loc_1400070F8 里是PresentMultiplaneOverlay头部字节

Interval.QuadPart = -50000000i64;
KeDelayExecutionThread(0, 0, &Interval);  // 恢复hook
KeStackAttachProcess(Dwm, &ApcState);
if ( BaseAddress )
{
    if ( HookMem )
    {
        sub_140001B30();
        if ( MmIsAddressValid(PresentMultiplaneOverlay) )
        {
            v17 = IoAllocateMdl(PresentMultiplaneOverlay, 0x100u, 0, 0, 0i64);
            MmProbeAndLockPages(v17, 1, IoReadAccess);
            v18 = MmMapLockedPagesSpecifyCache(v17, 0, MmNonCached, 0i64, 0, 0x10u);// mdl强写
            if ( v18 )
            {                                   // 
                // 48 8B C4              - mov rax,rsp
                // 55                    - push rbp
                // 56                    - push rsi
                // 57                    - push rdi
                // 41 54                 - push r12
                // 41 55                 - push r13
                // 41 56                 - push r14
                // 41 57                 - push r15
                *(_QWORD *)v18 = loc_1400070F8;
                v18[2] = loc_140007100;
                *((_WORD *)v18 + 6) = loc_140007104;
            }
            MmUnmapLockedPages(v18, v17);
            MmUnlockPages(v17);
            IoFreeMdl(v17);
        }
    }
}
KeUnstackDetachProcess(&ApcState);

延迟15秒释放shellcode

不用解释

KeUnstackDetachProcess(&ApcState);
Interval.QuadPart = -15000000i64;         // 释放shellcode
KeDelayExecutionThread(0, 0, &Interval);
KeStackAttachProcess(Dwm, &ApcState);
if ( BaseAddress )
{
    if ( HookMem )
    {
        ZwFreeVirtualMemory((HANDLE)0xFFFFFFFFFFFFFFFFi64, &BaseAddress, &RegionSize, 0x4000u);// 释放shellcode
        ZwFreeVirtualMemory((HANDLE)0xFFFFFFFFFFFFFFFFi64, &HookMem, &v23, 0x4000u);
    }
}
KeUnstackDetachProcess(&ApcState);

完整分析

void inject_shellcode()
{
  __int64 D3DCompile; // r15
  void *PresentMultiplaneOverlay; // rsi
  struct _KPROCESS *DwmProcess; // rax
  struct _KPROCESS *Dwm; // rdi
  HANDLE ProcessId; // rbx
  char *v5; // rbx
  char *v6; // rcx
  bool i; // cf
  char *v8; // r14
  unsigned int v9; // edx
  __int64 v10; // rcx
  unsigned int v11; // edx
  __int64 v12; // rcx
  char *v13; // rax
  struct _MDL *Mdl; // rbx
  char *v15; // rax
  char *v16; // rdx
  struct _MDL *v17; // rbx
  _DWORD *v18; // rax
  PVOID BaseAddress; // [rsp+38h] [rbp-49h] BYREF
  PVOID HookMem; // [rsp+40h] [rbp-41h] BYREF
  union _LARGE_INTEGER Interval; // [rsp+48h] [rbp-39h] BYREF
  ULONG_PTR RegionSize; // [rsp+50h] [rbp-31h] BYREF
  ULONG_PTR v23; // [rsp+58h] [rbp-29h] BYREF
  void *Handle; // [rsp+60h] [rbp-21h] BYREF
  __int64 v25; // [rsp+68h] [rbp-19h]
  struct _KAPC_STATE ApcState; // [rsp+70h] [rbp-11h] BYREF
  __int64 v27[2]; // [rsp+A0h] [rbp+1Fh] BYREF
  unsigned int v28; // [rsp+B0h] [rbp+2Fh]
  int v29; // [rsp+B4h] [rbp+33h]

  v23 = 0x1000i64;
  D3DCompile = 0i64;
  BaseAddress = 0i64;
  PresentMultiplaneOverlay = 0i64;
  HookMem = 0i64;
  RegionSize = 0x30BAi64;
  DwmProcess = GetDwmProcess();
  Dwm = DwmProcess;
  if ( DwmProcess )
  {
    Handle = 0i64;
    v25 = 0i64;
    ProcessId = PsGetProcessId(DwmProcess);
    GetModuleHandle(ProcessId, &Handle, "D3DCOMPILER_47.dll");// 从Ldr链里获取模块地址
    KeStackAttachProcess(Dwm, &ApcState);       // 附加DWM
    if ( Handle )                               // 如果模块存在
      D3DCompile = GetProAddress((__int64)Handle, (__int64)"D3DCompile");// 获取函数D3DCompile地址
    KeUnstackDetachProcess(&ApcState);          // 解除附加
    Handle = 0i64;
    v25 = 0i64;
    GetModuleHandle(ProcessId, &Handle, "dxgi.dll");// 获取dxgi模块地址
    KeStackAttachProcess(Dwm, &ApcState);
    v5 = (char *)Handle;
    if ( Handle )
    {
      v6 = (char *)Handle;
      for ( i = Handle < (char *)Handle + v25; i; i = v6 < (char *)Handle + v25 )
      {
        if ( *(_QWORD *)v6 == qword_140004000 && *((_QWORD *)v6 + 1) == qword_140004008 && v6[0x10] == byte_140004010 )// 搜索特征码 PresentMultiplaneOverlay
        {
          PresentMultiplaneOverlay = v6;
          break;
        }
        ++v6;
      }
    }
    if ( VersionInformation.dwBuildNumber == 17134 && Handle )// 如果为1803
    {
      v8 = (char *)Handle + v25;
      while ( v5 < v8 )
      {
        if ( !memcmp(v5, &unk_140004018, 0x15ui64) )// 搜索特征码
        {
          PresentMultiplaneOverlay = v5;
          break;
        }
        ++v5;
      }
    }
    KeUnstackDetachProcess(&ApcState);
    if ( D3DCompile && PresentMultiplaneOverlay )// 老方案 只不过放驱动里了
    {
      KeStackAttachProcess(Dwm, &ApcState);
      ZwAllocateVirtualMemory((HANDLE)0xFFFFFFFFFFFFFFFFi64, &BaseAddress, 0i64, &RegionSize, 0x1000u, 0x40u);// 申请shellcode 内存
      ZwAllocateVirtualMemory((HANDLE)0xFFFFFFFFFFFFFFFFi64, &HookMem, 0i64, &v23, 0x1000u, 0x40u);// hook内存?
      if ( BaseAddress && HookMem )
      {
        memcpy_s(BaseAddress, 0x30BAui64, &unk_140005A00, 0x16E6ui64);// 复制shellcode 到申请的内存中
        v9 = 0;
        v10 = 0i64;
        do
        {
          ++v9;
          *((_BYTE *)BaseAddress + v10++) ^= 0xC3u;
        }
        while ( v9 < 0x16E6 );                  // 解密shellcode
        memcpy_s((char *)BaseAddress + 0x16E6, 0x19D4ui64, dword_140004030, 0x19C4ui64);// 复制VmOpcodeTable到申请的内存中
        v11 = 0;
        v12 = 0i64;
        do
        {
          ++v11;
          *((_BYTE *)BaseAddress + v12 + 5862) ^= 0xCCu;// 解密 VmOpcodeTable
          ++v12;
        }
        while ( v11 < 0x19C4 );
        *(_QWORD *)((char *)BaseAddress + 0x30AA) = D3DCompile;
        *(_QWORD *)((char *)BaseAddress + 0x30B2) = HookMem;
        *(_DWORD *)((char *)BaseAddress + dword_1400059F4) = 0x30A6 - dword_1400059F4;
        *(_DWORD *)((char *)BaseAddress + dword_1400059F8) = 0x30AE - dword_1400059F8;
        *(_DWORD *)((char *)BaseAddress + dword_1400070EC) = 0x671;
        *(_DWORD *)((char *)BaseAddress + dword_1400070E8) = 0x16E2 - dword_1400070E8;
        memcpy_s(HookMem, 14ui64, &qword_1400070F8, 14ui64);// PresentMultiplaneOverlay 头部字节码
        v13 = (char *)HookMem;
        *(_DWORD *)((char *)HookMem + 15) = (_DWORD)PresentMultiplaneOverlay + 14;
        *(_DWORD *)(v13 + 0x17) = ((unsigned __int64)PresentMultiplaneOverlay + 14) >> 32;
        v13[14] = 0x68;
        *(_DWORD *)(v13 + 0x13) = 0x42444C7;
        v13[27] = 0xC3;
      }
      KeUnstackDetachProcess(&ApcState);
      KeStackAttachProcess(Dwm, &ApcState);
      if ( BaseAddress && HookMem )
      {
        if ( MmIsAddressValid(PresentMultiplaneOverlay) )
        {
          Mdl = IoAllocateMdl(PresentMultiplaneOverlay, 0x100u, 0, 0, 0i64);
          MmProbeAndLockPages(Mdl, 1, IoReadAccess);
          v15 = (char *)MmMapLockedPagesSpecifyCache(Mdl, 0, MmNonCached, 0i64, 0, 0x10u);// hook
          if ( v15 )
          {                                     // 68 00000000           - push 00000000 { 0 }
                                                // C7 44 24 04 00000000  - mov [rsp+04],00000000 { 0 }
                                                // C3                    - ret 
                                                // shellcode
            v16 = (char *)BaseAddress + dword_1400070F0;// sub_860,各种初始化
            *(_DWORD *)(v15 + 1) = (_DWORD)v16;
            *(_DWORD *)(v15 + 9) = HIDWORD(v16);// 往里面写数据
            *v15 = 0x68;                        // push shellcode sub_860
            *(_DWORD *)(v15 + 5) = 69485767;    // mov [rsp+04],00000000
            v15[13] = 0xC3;                     // ret
          }
          MmUnmapLockedPages(v15, Mdl);
          MmUnlockPages(Mdl);
          IoFreeMdl(Mdl);
        }
        v27[0] = (__int64)BaseAddress;
        v29 = 0;
        v27[1] = 0x30BAi64;
        v28 = (unsigned int)PsGetProcessId(Dwm);
        sub_140001A84((__int64)v27);
      }
      KeUnstackDetachProcess(&ApcState);
      Interval.QuadPart = -50000000i64;
      KeDelayExecutionThread(0, 0, &Interval);  // 恢复hook
      KeStackAttachProcess(Dwm, &ApcState);
      if ( BaseAddress )
      {
        if ( HookMem )
        {
          sub_140001B30();
          if ( MmIsAddressValid(PresentMultiplaneOverlay) )
          {
            v17 = IoAllocateMdl(PresentMultiplaneOverlay, 0x100u, 0, 0, 0i64);
            MmProbeAndLockPages(v17, 1, IoReadAccess);
            v18 = MmMapLockedPagesSpecifyCache(v17, 0, MmNonCached, 0i64, 0, 0x10u);// mdl强写
            if ( v18 )
            {                                   // 
                                                // 48 8B C4              - mov rax,rsp
                                                // 55                    - push rbp
                                                // 56                    - push rsi
                                                // 57                    - push rdi
                                                // 41 54                 - push r12
                                                // 41 55                 - push r13
                                                // 41 56                 - push r14
                                                // 41 57                 - push r15
              *(_QWORD *)v18 = qword_1400070F8;
              v18[2] = dword_140007100;
              *((_WORD *)v18 + 6) = word_140007104;
            }
            MmUnmapLockedPages(v18, v17);
            MmUnlockPages(v17);
            IoFreeMdl(v17);
          }
        }
      }
      KeUnstackDetachProcess(&ApcState);
      Interval.QuadPart = -15000000i64;         // 释放shellcode
      KeDelayExecutionThread(0, 0, &Interval);
      KeStackAttachProcess(Dwm, &ApcState);
      if ( BaseAddress )
      {
        if ( HookMem )
        {
          ZwFreeVirtualMemory((HANDLE)0xFFFFFFFFFFFFFFFFi64, &BaseAddress, &RegionSize, 0x4000u);// 释放shellcode
          ZwFreeVirtualMemory((HANDLE)0xFFFFFFFFFFFFFFFFi64, &HookMem, &v23, 0x4000u);
        }
      }
      KeUnstackDetachProcess(&ApcState);
    }
  }
}

Patch Free

大概流程

注册loadimg回调

比赛sys加载 触发回调

![image-20220423202130093](决赛 writeup.assets\image-20220423202130093.png)

然后jmp 到

loc_1400019EA:                ; CODE XREF: sub_1400014A0+5D↑j
.text:00000001400019EA                                                             ; sub_1400014A0+173↑j
.text:00000001400019EA                                                             ; sub_1400014A0+17C↑j
.text:00000001400019EA 48 8B 4D 37                   mov     rcx, [rbp+57h+var_20]
.text:00000001400019EE 48 33 CC                      xor     rcx, rsp              ; StackCookie
.text:00000001400019F1 E8 EA 01 00 00                call    __security_check_cookie
.text:00000001400019F1
.text:00000001400019F6 4C 8D 9C 24 C0 00 00 00       lea     r11, [rsp+0D0h+var_10]
.text:00000001400019FE 49 8B 5B 20                   mov     rbx, [r11+20h]
.text:0000000140001A02 49 8B 73 28                   mov     rsi, [r11+28h]
.text:0000000140001A06 49 8B 7B 30                   mov     rdi, [r11+30h]
.text:0000000140001A0A 4D 8B 63 38                   mov     r12, [r11+38h]
.text:0000000140001A0E 49 8B E3                      mov     rsp, r11
.text:0000000140001A11 41 5F                         pop     r15
.text:0000000140001A13 41 5E                         pop     r14
.text:0000000140001A15 5D                            pop     rbp
.text:0000000140001A16 C3                            retn

Mdl强写

void MdlCopyMemory(PVOID address,PVOID buffer,size_t size)
{
	__try
	{
		if (MmIsAddressValid((PVOID)address))
		{
			auto pMdl = IoAllocateMdl(address, size, FALSE, FALSE, nullptr);
			if (pMdl)
			{
				MmBuildMdlForNonPagedPool(pMdl);

				auto lock = MmMapLockedPagesSpecifyCache(pMdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);

				if (lock)
				{
					RtlCopyMemory(lock, buffer, size);
					MmUnmapLockedPages(lock, pMdl);
				}
				ExFreePool(pMdl);

			}
		}
	}
	__except (1)
	{

	}

}

Lodimg

VOID LoadImageNotify(
	_In_ PUNICODE_STRING FullImageName,
	_In_ HANDLE ProcessId,
	_In_ PIMAGE_INFO ImageInfo
)
{
	if (FullImageName != nullptr && MmIsAddressValid(FullImageName))
	{
		if (ProcessId == 0) // 是否是驱动
		{
			auto ImageName = FullImageName->Buffer;
			if (wcsstr(ImageName, L"2022GameSafeRace.sys"))
			{
				auto PatchFree = reinterpret_cast<uint8_t*>(ImageInfo->ImageBase) + 0x18a4;
				auto JmpAddress = reinterpret_cast<uint8_t*>(ImageInfo->ImageBase) + 0x19ea;
				char jmp[] = {
					0xe9,0x00,0x00,0x00,0x00
				};
				*(uint32_t*)(jmp + 1) = (ULONG64)(JmpAddress - PatchFree + 5);

				MdlCopyMemory(PatchFree, &jmp, sizeof(jmp));
			}
		}
	}
}

完整代码

#include <ntifs.h>
#include <ntdef.h>
#include <ntstatus.h>
#include <cstdint>
#define DPRINT(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, __VA_ARGS__)
void MdlCopyMemory(PVOID address,PVOID buffer,size_t size)
{
	__try
	{
		if (MmIsAddressValid((PVOID)address))
		{
			auto pMdl = IoAllocateMdl(address, size, FALSE, FALSE, nullptr);
			if (pMdl)
			{
				MmBuildMdlForNonPagedPool(pMdl);

				auto lock = MmMapLockedPagesSpecifyCache(pMdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority);

				if (lock)
				{
					RtlCopyMemory(lock, buffer, size);
					MmUnmapLockedPages(lock, pMdl);
				}
				ExFreePool(pMdl);

			}
		}
	}
	__except (1)
	{

	}

}
VOID LoadImageNotify(
	_In_ PUNICODE_STRING FullImageName,
	_In_ HANDLE ProcessId,
	_In_ PIMAGE_INFO ImageInfo
)
{
	if (FullImageName != nullptr && MmIsAddressValid(FullImageName))
	{
		if (ProcessId == 0) // 是否是驱动
		{
			auto ImageName = FullImageName->Buffer;
			if (wcsstr(ImageName, L"2022GameSafeRace.sys"))
			{
				auto PatchFree = reinterpret_cast<uint8_t*>(ImageInfo->ImageBase) + 0x18a4;
				auto JmpAddress = reinterpret_cast<uint8_t*>(ImageInfo->ImageBase) + 0x19ea;
				char jmp[] = {
					0xe9,0x00,0x00,0x00,0x00
				};
				*(uint32_t*)(jmp + 1) = (ULONG64)(JmpAddress - PatchFree + 5);

				MdlCopyMemory(PatchFree, &jmp, sizeof(jmp));
			}
		}
	}
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{
	PsRemoveLoadImageNotifyRoutine(LoadImageNotify);
}

EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString)
{
	pDriverObj->DriverUnload = DriverUnload;
	auto status = PsSetLoadImageNotifyRoutine(LoadImageNotify);
	return status;
}

Exe分析

WinMain下段跟

CreateThread(0i64, 0i64, (LPTHREAD_START_ROUTINE)sub_140003530, 0i64, 0, &ThreadId);

发现这段参加线程

点进去一看

发现NtQuerySystemInformation

明显是通过 NtQuerySystemInformation触发回调

__int64 __fastcall sub_140003530(PVOID Parameter)
{
  HANDLE ProcessHeap; // rax
  char *v2; // rdx
  __int64 result; // rax
  ULONG ReturnLength; // [rsp+38h] [rbp+10h] BYREF

  ProcessHeap = GetProcessHeap();
  v2 = (char *)HeapAlloc(ProcessHeap, 8u, 0x28ui64);
  result = 0i64;
  *(_OWORD *)v2 = 0i64;
  *((_OWORD *)v2 + 1) = 0i64;
  *((_QWORD *)v2 + 4) = 0i64;
  if ( v2 )
  {
    *((_DWORD *)v2 + 2) = 0;
    *((_DWORD *)v2 + 1) = 1;
    *(_DWORD *)v2 = 1380011588;
    *((_DWORD *)v2 + 3) = 20;
    *(_QWORD *)(v2 + 20) = 8193i64;
    *((_QWORD *)v2 + 4) = D3DCompile;
    ReturnLength = 40;
    NtQuerySystemInformation(SystemFirmwareTableInformation, v2, 0x28u, &ReturnLength);
    return 0i64;
  }
  return result;
}

shellcode 分析

dump下shellcode 分析

卧槽? 这不是咱老朋友吗

不过虚拟机进化了

DrawRect

__int64 __fastcall DrawRect(
        int a1,
        int a2,
        int a3,
        int a4,
        float a5,
        __int64 a6,
        __int64 a7,
        __int64 a8,
        __int64 a9,
        __int64 a10)
{
  __int64 v14; // r14
  unsigned int v15; // ebx
  int v16; // ecx
  float v17; // xmm9_4
  float v18; // xmm11_4
  float v19; // xmm7_4
  float v20; // xmm10_4
  float *v21; // rcx
  float v22; // xmm0_4
  float v23; // xmm8_4
  float v24; // xmm6_4
  float v25; // xmm3_4
  float v26; // xmm1_4
  float v27; // xmm8_4
  float v28; // xmm7_4
  float v29; // xmm5_4
  float v30; // xmm4_4
  float v31; // xmm2_4
  __int64 v32; // rax
  float *v34; // [rsp+30h] [rbp-C8h] BYREF
  char v35[8]; // [rsp+40h] [rbp-B8h] BYREF
  float v36; // [rsp+48h] [rbp-B0h]
  float v37; // [rsp+4Ch] [rbp-ACh]
  int v38; // [rsp+108h] [rbp+10h] BYREF
  int v39; // [rsp+110h] [rbp+18h] BYREF
  int v40; // [rsp+118h] [rbp+20h] BYREF

  v14 = a6;
  v38 = 1;
  v15 = LODWORD(a5) + (a3 ^ (a1 + a2)) % 256 - a4 % 256;
  (*(void (__fastcall **)(__int64, int *, char *))(*(_QWORD *)a6 + 760i64))(a6, &v38, v35);
  v16 = (a3 ^ (a2 * a1)) % 256 - (a4 >> 8) % 256;
  v17 = (float)(v37 - (float)(2 * (v16 + a2) - 1)) / v37;
  v18 = (float)(v37 - (float)(2 * a2 + 99)) / v37;
  v19 = (float)((float)(2 * (v16 + a1) - 1) - v36) / v36;
  v20 = (float)((float)(2 * a1 + 99) - v36) / v36;
  (*(void (__fastcall **)(__int64, __int64, _QWORD, __int64, _DWORD, float **))(*(_QWORD *)v14 + 112i64))(
    v14,
    a7,
    0i64,
    4i64,
    0,
    &v34);
  v21 = v34;
  a5 = 255.0;
  v34[2] = (float)0;
  v22 = a5;
  v23 = (float)((a3 ^ (a2 + a1 * (a2 + 1))) % 256 - (a4 >> 16) % 256);
  v24 = v23 + v19;
  v25 = v23 + v17;
  *v21 = v23 + v19;
  v26 = v23 + v20;
  v21[1] = v23 + v17;
  v27 = v23 + v18;
  v28 = (float)BYTE2(v15) / v22;
  v29 = (float)(unsigned __int8)(v15 >> 12) / v22;
  v30 = (float)(unsigned __int8)v15 / v22;
  v21[3] = v28;
  v21[4] = v29;
  v31 = (float)HIBYTE(v15) / v22;
  v21[6] = v31;
  v21[9] = (float)0;
  v21[13] = v31;
  v21[16] = (float)0;
  v21[20] = v31;
  v21[27] = v31;
  v21[5] = v30;
  v21[7] = v26;
  v21[8] = v25;
  v21[10] = v28;
  v21[11] = v29;
  v21[12] = v30;
  v21[14] = v24;
  v21[15] = v27;
  v21[17] = v28;
  v21[18] = v29;
  v21[19] = v30;
  v21[21] = v26;
  v21[22] = v27;
  v21[24] = v28;
  v21[25] = v29;
  v21[26] = v30;
  v21[23] = (float)0;
  (*(void (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)v14 + 120i64))(v14, a7, 0i64);
  v32 = *(_QWORD *)v14;
  v40 = 28;
  v39 = 0;
  (*(void (__fastcall **)(__int64, _QWORD, __int64, __int64 *, int *, int *))(v32 + 144))(
    v14,
    0i64,
    1i64,
    &a7,
    &v40,
    &v39);
  (*(void (__fastcall **)(__int64, __int64))(*(_QWORD *)v14 + 192i64))(v14, 5i64);
  (*(void (__fastcall **)(__int64, __int64))(*(_QWORD *)v14 + 136i64))(v14, a8);
  (*(void (__fastcall **)(__int64, __int64, _QWORD, _QWORD))(*(_QWORD *)v14 + 88i64))(v14, a9, 0i64, 0i64);
  (*(void (__fastcall **)(__int64, __int64, _QWORD, _QWORD))(*(_QWORD *)v14 + 72i64))(v14, a10, 0i64, 0i64);
  (*(void (__fastcall **)(__int64, _QWORD, _QWORD, _QWORD))(*(_QWORD *)v14 + 184i64))(v14, 0i64, 0i64, 0i64);
  return (*(__int64 (__fastcall **)(__int64, __int64))(*(_QWORD *)v14 + 104i64))(v14, 4i64);
}

加强版虚拟机

__int64 __fastcall sub_420(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6, __int64 a7)
{
  unsigned __int64 idx; // rsi
  unsigned __int64 vidx; // r8
  signed int branch; // ecx
  unsigned __int64 v12; // rdx
  __int64 v13; // rcx
  unsigned int v14; // r9d
  __int64 v15; // r8
  __int64 v16; // r9
  unsigned int v17; // edx
  unsigned __int64 v18; // r10
  unsigned __int64 v19; // rcx
  unsigned int v20; // r9d
  int v21; // r9d
  int v22; // eax
  __int64 result; // rax
  int reg[10]; // [rsp+60h] [rbp-21h] BYREF

  idx = 0i64;
  memset(reg, 0, 32);
  reg[8] = 50;
  reg[9] = 50;
  do
  {
    vidx = idx;
    branch = opcode[idx];
    if ( branch > (int)0x9A8ECD52 )
    {
      switch ( branch )
      {
        case 0xEE2362FC:
          ++idx;
          v21 = reg[0];
          v22 = reg[0] * (reg[1] + 1);
          reg[0] = opcode[idx] ^ 0x414345;
          reg[1] = (reg[0] ^ (reg[1] + v21)) % 256
                 + (((reg[0] ^ (v21 * reg[1])) % 256 + (((reg[0] ^ (reg[1] + v22)) % 256) << 8)) << 8);
          break;
        case 0xEE69524A:
          v19 = 0i64;
          v20 = opcode[vidx + 1];
          opcode[idx] = -1;
          opcode[vidx + 1] = -1;
          if ( idx != 1 )
          {
            do
              opcode[v19++] ^= v20;
            while ( v19 < idx - 1 );
          }
          ++idx;
          break;
        case 0xFF4578AE:
          idx += 2i64;
          v16 = (int)opcode[vidx + 1];
          v17 = opcode[idx];
          if ( (_DWORD)v16 )
          {
            v18 = idx;
            do
            {
              opcode[++v18] ^= v17;
              v17 = opcode[v18 - 1] + 0x12345678 * v17;
              --v16;
            }
            while ( v16 );
          }
          opcode[vidx] = -1;
          opcode[vidx + 1] = -1;
          opcode[idx] = -1;
          break;
        case 0x1132EADF:
          idx += 2i64;
          reg[opcode[idx]] = opcode[vidx + 1];
          break;
        default:
          if ( branch == 0x7852AAEF && opcode[0] == 0xEE69624A && opcode[1] == 0x689EDC0A && opcode[2] == 0x98EFDBC9 )
            sub_0(reg[4], reg[5], reg[6], reg[7], 0xFF2DDBE7, a3, a4, a5, a6, a7);
          break;
      }
    }
    else
    {
      switch ( branch )
      {
        case 0x9A8ECD52:
          reg[0] -= reg[1];
          break;
        case 0x88659264:
          idx += 2i64;
          v12 = idx;
          v13 = (int)opcode[vidx + 1];
          v14 = opcode[idx];
          opcode[vidx] = -1;
          opcode[vidx + 1] = -1;
          v15 = v13;
          opcode[idx] = -1;
          if ( (_DWORD)v13 )
          {
            do
            {
              opcode[++v12] ^= v14;
              --v15;
            }
            while ( v15 );
          }
          break;
        case 0x89657EAD:
          reg[0] += reg[1];
          break;
        case 0x8E7CADF2:
          idx += 2i64;
          reg[opcode[idx]] = reg[opcode[vidx + 1]];
          break;
        case 0x9645AAED:
          if ( opcode[0] == 0xEE69624A && opcode[1] == 0x689EDC0A && opcode[2] == 0x98EFDBC9 )
            sub_0(reg[4], reg[5], reg[6], reg[7], 0xFFFFFF00, a3, a4, a5, a6, a7);
          break;
        case 0x9645AEDC:
          idx = 0x671i64;
          break;
      }
    }
    result = 0x671i64;
    ++idx;
  }
  while ( idx < 0x671 );
  return result;
}

虚拟机分析

虚拟机经过六次解密达到最终结果

====ExecVirtual[0]====
Reg[8] = 50
Reg[9] = 50
-> Xor 1
-> VMEnd
====ExecVirtual[1]====
Reg[8] = 50
Reg[9] = 50
-> Xor 1
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],3301906)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7631989)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 432
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],2299116)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 504
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9843946)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> VMEnd
====ExecVirtual[2]====
Reg[8] = 50
Reg[9] = 50
-> Xor 1
Reg[0] = Reg[8]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],3301906)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7631989)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 432
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],2299116)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 504
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9843946)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> VMEnd
====ExecVirtual[3]====
Reg[8] = 50
Reg[9] = 50
-> Xor 1
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7882222)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],4728102)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],3301906)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7631989)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 432
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],2299116)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 504
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9843946)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> VMEnd
====ExecVirtual[4]====
Reg[8] = 50
Reg[9] = 50
-> Xor 1
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9843546)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9851444)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7882222)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],4728102)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],3301906)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7631989)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 432
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],2299116)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
Reg[0] = Reg[8]
Reg[1] = 504
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9843946)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> VMEnd
====ExecVirtual[5]====
Reg[8] = 50
Reg[9] = 50
-> Xor 1
Reg[0] = Reg[8]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9844004)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],11451615)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],8734638)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9864618)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9843546)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9851444)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7882222)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],4728102)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],3301906)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7631989)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 432
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],2299116)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 504
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9843946)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

-> VMEnd
====ExecVirtual[6]====
Reg[8] = 50
Reg[9] = 50
-> Xor 3
-> Xor 2
Reg[0] = Reg[8]
Reg[4] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = 1000
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],5392533)
Reg[3] = Reg[0]
Reg[0] = Reg[1]
Reg[1] = Reg[3]
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[5]
Reg[1] = 500
Reg[0] -= Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],5934636)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[4] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = 1000
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9984722)
Reg[3] = Reg[0]
Reg[0] = Reg[1]
Reg[1] = Reg[3]
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

-> Xor 3
Reg[0] = Reg[8]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],11102301)
Reg[3] = Reg[0]
Reg[0] = Reg[3]
Reg[1] = Reg[3]
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[4] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = 1000
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
-> Xor 2
Reg[5] = Reg[0]
Reg[0] = Reg[5]
Reg[1] = 500
Reg[0] -= Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7888111)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9846439)
Reg[3] = Reg[0]
Reg[0] = Reg[1]
Reg[1] = Reg[3]
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = 1000
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[5]
Reg[1] = 500
Reg[0] -= Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],4608533)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 216
Reg[0] += Reg[1]
-> Xor 3
Reg[5] = Reg[0]
Reg[0] = Reg[5]
Reg[1] = 500
Reg[0] -= Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],8744398)
Reg[3] = Reg[0]
Reg[0] = Reg[1]
Reg[1] = Reg[3]
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = 1000
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7703662)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[5]
Reg[1] = 500
Reg[0] -= Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
-> Xor 3
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],10004148)
Reg[3] = Reg[0]
Reg[#] = Reg[1]
Reg[1] = Reg[3]
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = 1000
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],8744654)
Reg[3] = Reg[0]
Reg[0] = Reg[1]
Reg[1] = Reg[3]
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 720
Reg[0] += Reg[1]
Reg[8] = Reg[0]
-> Xor 2
Reg[0] = Reg[8]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],11271250)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 72
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],8744654)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 144
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
-> Xor 3
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9852138)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],8725420)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 288
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],8841932)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],15348293)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 144
Reg[0] -= Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],8735468)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9846222)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],10022468)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7905811)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],5399353)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],8935246)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],1197146)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9851459)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],11150308)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 432
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],11150472)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 504
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9851428)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[8] = Reg[0]
Reg[0] = Reg[8]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],2504020)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],87160)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9844004)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],11451615)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 72
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],8734638)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9864618)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9843546)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9851444)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 144
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7882222)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 216
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],4728102)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],3301906)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 360
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],7631989)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 432
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],2299116)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

Reg[0] = Reg[8]
Reg[1] = 504
Reg[0] += Reg[1]
Reg[4] = Reg[0]
Reg[0] = Reg[9]
Reg[1] = 288
Reg[0] += Reg[1]
Reg[5] = Reg[0]
Reg[0] = Reg[4]
Reg[1] = Reg[5]
Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],9843946)
Reg[6] = Reg[0]
Reg[7] = Reg[1]
-> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFF2DDBE7)

-> VMEnd

还是老样子

Reg[1] = 1000
Reg[0] -= Reg[1]

这里1000,500导致的坐标负数

Reg[0],Reg[1] <- Decrypt(Reg[0],Reg[1],5392533)
Reg[3] = Reg[0]
Reg[0] = Reg[1]
Reg[1] = Reg[3]
Reg[6] = Reg[0]
Reg[7] = Reg[1]

这里导致的交换reg[5] reg[6]

生成新表

patch 500 1000导致的负数,

patch 交换 reg[5] reg[6]

std::vector<Opcode> VM::GenFixOpcode(std::vector<uint32_t>& Vopcodes)
{
	int reg[10] = { 0 };
	uint32_t idx = 0;
	std::vector<Opcode> outData;
	//printf_s("Reg[8] = 50\n");
	//printf_s("Reg[9] = 50\n");
	reg[8] = 50;
	reg[9] = 50;
	do
	{
		auto vidx = idx;
		auto branch = Vopcodes[idx];

		if (branch) {
			switch (branch) {
			case operate::Decrypt: {
				++idx;
				auto x = reg[0];
				auto y = reg[1];
				auto v = x * (y + 1);;
				reg[0] = Vopcodes[idx] ^ 'ACE';
				reg[1] = ((reg[0] ^ (y + x)) % 256
					+ (((reg[0] ^ (x * y)) % 256 + (((reg[0] ^ (y + v)) % 256) << 8)) << 8));
				printf_s("EE2362FC Reg[0],Reg[1] <- Draw(%d,%d,%x,%x)\n", reg[4],reg[5],reg[0], reg[1]);
				//printf_s("EE2362FC Reg[0],Reg[1] <- Decrypt(%d,%d)\n", reg[0], reg[2]);
				break;
			}
			case operate::Xor1: {
				auto i = 0i64;
				auto key = Vopcodes[vidx + 1];
				Vopcodes[idx] = -1;
				Vopcodes[vidx + 1] = -1;
				if (idx != 1)
				{
					do
						Vopcodes[i++] ^= key;
					while (i < idx - 1);
				}
				++idx;
				//printf_s("EE69524A -> Xor 1\n");

				break;
			}
			case operate::Xor2: {
				idx += 2i64;
				auto count = Vopcodes[vidx + 1];
				auto key = Vopcodes[idx];
				if (count)
				{
					auto vidx_ = idx;
					do
					{
						Vopcodes[++vidx_] ^= key;
						key = Vopcodes[vidx_ - 1] + 0x12345678 * key;
						--count;
					} while (count);
				}
				Vopcodes[vidx] = -1;
				Vopcodes[vidx + 1] = -1;
				Vopcodes[idx] = -1;
				//printf_s("FF4578AE -> Xor 2\n");
				break;
			}
			case operate::Xor3: {
				idx += 2i64;
				auto sidx = idx;
				auto count = Vopcodes[vidx + 1];
				auto key = Vopcodes[idx];
				Vopcodes[vidx] = -1;
				Vopcodes[vidx + 1] = -1;
				Vopcodes[idx] = -1;
				if (count)
				{
					do
					{
						Vopcodes[++sidx] ^= key;
						--count;
					} while (count);
					//printf_s("88659264 -> Xor 3\n");

				}
				break;

			}
			case operate::RegSub:
			{
				reg[0] -= reg[1];
				//printf_s("9A8ECD52 Reg[0] -= Reg[1]\n");
				break;
			}

			case operate::RegAdd:
				reg[0] += reg[1];
				//printf_s("89657EAD Reg[0] += Reg[1]\n");
				break;
			case operate::RegSwap:
			{
				idx += 2i64;
				if (Vopcodes[idx] == 0 && Vopcodes[vidx + 1] == 1)
					Vopcodes[idx] = 3;

				reg[Vopcodes[idx]] = reg[Vopcodes[vidx + 1]];
				
				//printf_s("8E7CADF2 Reg[%d] = Reg[%d]\n", Vopcodes[idx], Vopcodes[vidx + 1]);
				break;

			}
			case operate::RegAssignment: {
				idx += 2i64;
				if (Vopcodes[vidx + 1] == 1000 || Vopcodes[vidx + 1] == 500)
					Vopcodes[vidx + 1] = 0;
				reg[Vopcodes[idx]] = Vopcodes[vidx + 1];

				//printf_s("1132EADF Reg[%d] = %d\n", Vopcodes[idx], Vopcodes[vidx + 1]);
				break;
			}
			case 0x9645AAED:
			{
				//if (Vopcodes[0] == 0xEE69624A && 
				//	Vopcodes[1] == 0x689EDC0A && 
				//	Vopcodes[2] == 0x98EFDBC9)
				//	printf_s("9645AAED -> Draw(Reg[4],Reg[5],Reg[6],Reg[7],0xFFFFFF00)\n\n");
				// 压根没到这个分支
				break;
			}
			case operate::Draw:
			{
				if (Vopcodes[0] == 0xEE69624A && Vopcodes[1] == 0x689EDC0A && Vopcodes[2] == 0x98EFDBC9)
				{
					auto GenRegAssignment = [](int r,int value) {
						Opcode op;
						op.Type = operate::RegAssignment;
						op.Data.Assignment.Reg = r;
						op.Data.Assignment.Value = value;
						return op;
					};
					for (size_t i = 4; i <= 7; i++)
					{
						outData.push_back(GenRegAssignment(i, reg[i]));
					}
					Opcode op;
					op.Type = operate::Draw;
					outData.push_back(op);

					//printf_s("7852AAEF -> Draw(%d,%d,%d,%d,0xFF2DDBE7)\n\n", reg[4], reg[5], reg[6], reg[7]);

				}
				break;
			}
			case operate::VmEnd: {
				printf_s("9645AEDC -> VMEnd\n");
				idx = 0x671i64;
				break;
			}
			}
		}

		idx++;

	} while (idx < 0x671);
	return outData;
}

通过模拟执行得到rect信息 利用这些信息生成新的opcode

std::vector<uint32_t> VM::OutVituralOpCodeTable(const std::vector<Opcode>& opcodes)
{
	std::vector<uint32_t> outData;
	outData.push_back(0xEE69624A);
	outData.push_back(0x689EDC0A);
	outData.push_back(0x98EFDBC9);
	auto idx = 0;
	for (auto op : opcodes)
	{
		auto vidx = idx;
		switch (op.Type)
		{
		case operate::RegSwap: {

			outData.push_back(RegSwap);
			outData.push_back(op.Data.Swap.Target);
			outData.push_back(op.Data.Swap.Source);
			break;
		}
		case operate::RegAssignment:
		{

			outData.push_back(RegAssignment);
			outData.push_back(op.Data.Assignment.Value);

			outData.push_back(op.Data.Assignment.Reg);


			break;
		}
		case operate::Draw:
		{

			outData.push_back(Draw);
		}
		default:
			break;
		}
		idx++;
	}
	outData.push_back(operate::VmEnd);
	if (outData.size() < 0x671)
		outData.resize(0x671);
	return outData;
	
}

截图

方案1

在我的dll直接实现,刚好比赛驱动用比赛驱动的hook

ScreenGrab · microsoft/DirectXTK Wiki (github.com)

void screenshot(IDXGISwapChain* pSwapChain)
{
	ID3D11Device* device;

	HRESULT gd = pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&device);
	if (device && gd == S_OK)
	{
		//Get context
		ID3D11DeviceContext* context;
		device->GetImmediateContext(&context);
		
		//get back buffer
		ID3D11Texture2D* backbufferTex;
		HRESULT gb = pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backbufferTex);

		if (gb == S_OK)
		{
			HRESULT hr = DirectX::SaveWICTextureToFile(context, backbufferTex, GUID_ContainerFormatJpeg, L"d:\\dwm.jpg");
			if (hr == S_OK)
				cout << "截图成功" << endl;
		}
		//Capture Frame
	
	}

}

从交换链里获取Device

再GetBuffer

再调用 dxtk SaveWICTextureToFile 保存到文件

方案2

lainswork/dwm-screen-shot: 将shellcode注入dwm.exe以进行屏幕截取 (github.com)

lainswork/shellcode-factory: shellcode 生成框架 (github.com)

利用shellcode 生成框架

通过符号获取hook地址

修改页面属性

veh 捕获异常 hook 获取交换链

利用交换链 getbuffer

exe 直接读这个buff 绘制出来

其实和我的方案一一毛一样 除了是shellcode

方案3

Abusing DComposition to render on external windows | secret club

劫持dwm窗口应该是个思路吧

劫持线程到自己exe

应该可以截图到吧

没具体实现

方案4

NVidia 游戏内覆盖截图

他那个基于显卡 直接copy的显存 经朋友测试的确可以截到

本来想看看的 毕竟上次泄露nv的驱动源码 但是我电脑不支持此方案

NVIDIA Capture SDK | NVIDIA Developer

NvFBC nv的视频录制sdk 是直接从显存里copy数据

按理也可以截图

不过最高支持win10 1803 我win11 所以没办法

所以这里没有测试方案

video-sdk-samples/nvEncDXGIOutputDuplicationSample at master · NVIDIA/video-sdk-samples (github.com)

他官方推荐的代替方案

后来我又去实现了他文档放弃win10 所推荐的dx方案

IDXGIOutput 发现并不能截图dwm

![image-20220424192056570](决赛 writeup.assets\image-20220424192056570.png)

后续...

amd 方案

高级媒体框架 - GPU 打开 (gpuopen.com)

txfinal's People

Contributors

chordp avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.