查看原文
其他

看雪CTF.TSRC 2018 团队赛 第九题『谍战』 解题思路

小雪 看雪学院 2019-05-25


第九题《谍战》在今天(12月19日)中午12:00 结束攻击。


只有五支团队在这场逻辑严谨,情节紧张,风起云涌的“谍战”中存活了下来。本题出题团队GPUber 此次在防守方排名位居第二。




最新赛况战况一览


第九题之后,攻击方最新排名情况如下:


中午放题搬砖狗哭哭 的第一名宝座暂时无人撼动!Acehub从第6名上升至第4名,雨落星辰上升1名,至第5名。n0body 突进前10位。


或许,剧情会出乎所有人的预料,会有第三支团队冲出重围让所有人大跌眼镜吗?





第九题 点评


crownless:

解开“谍战”此题需要排除陷阱算法的干扰,方法是分析GUI并找到分析算法的位置是在Shader中。接着,此题考查了汇编语言以及三元一次方程组。因此,解开此题需要较为全面的计算机和数学基础。



第九题 出题团队简介


出题团队: GPUber






第九题 设计思路


由看雪论坛 supercolin 原创


0x01 前 言

 

工作一直都和 GPU 相关,于是想着出道题,能和 GPU 有些联系。

 


0x02 关键字

 

  • nana C++library

    这是最近写小工具用的比较多的一个 GUI 库,堆简单界面,事件处理都很简洁。


  • 字符串隐藏

    字符串往往是 crack 的入手点,本题利用 GPU render 完成。


  • 陷阱算法

    此算法照搬去年爱琴海 CrackMe 的海伦公式作为致敬。

  • Shader

    真正起作用的算法由 HLSL shader 完成。

 


0x03 细节介绍

 

输入预处理

这个环节由正则表达式处理。


由正则表达式"^([[:d:]]{10})([[:d:]]{10})([[:d:]]{10})$"及后续代码可以很容易分析出,合法的输入应是 30 位十进制数,每 10 位作为一个变量用于后续算法计算。


字符串隐藏

程序运行起来之后往往需要一个切入点。题目根据输入实时计算序列号的正确性,给出Wrong/Correct 的字符串提示信息。如果用常规的方法 disasm 后找到对应字符串,则很容易落入陷阱算法中,即使分析得到算法并且给出正确答案,依然无法显示输入序列号正确时应有的“Correct!”信息,令解题人怀疑自己分析有误从而迷惑解题人。

 

实际并非是对陷阱算法解题有误,而是提示信息并非由 nana GUI 完成,而是由 Dx11 采用对应字符串的顶点信息绘制完成。

 

首先,用 Blender 构造对应字符串并生成 mesh:


然后,将 mesh 导出为 wavefront obj 格式的 3D 模型,如下:


最后,对顶点及索引数据稍作处理,便于之后的 Dx11 进行绘制。详见代码中的相关部分。

 

因此解题的关键,是要能够判断出,提示信息是由 Dx11 完成,而非 GUI 上的label。事实上,GUI 上的 label 依然是存在的,只是由于 Dx11 swapchain 的关系,label 的显示被完全覆盖了。如果在代码中跳过 Dx11 的部分,输入陷阱算法的正确答案,可以看到 label 的内容是会做相应变化的。


陷阱算法

这里照搬了去年爱琴海 CrackMe的海伦公式算法,原题答案为 5e9a3f183e37f900。这里为了满足输入预处理中,总长度 30 位十进制数字且每 10个数字作为一个变量的要求,对原题答案稍作了一些变化:


0x5e9a3f18 == 1587167000

0x3e37f900 == 1043855616

1587167000 + 1043855616 == 2631022616

陷阱算法答案为:

(158716700010438556162631022616)


Dx11Render

根据预制好的顶点和索引数据(Correct及Wrong字符串),分别render两张texture做为srv,由shader 根据输入的 3 个数字进行计算,如果结果正确,则显示 Correct 对应的texture, 否则显示 Wrong 对应的 texture。具体过程可见代码,不再详细描述。这里考虑到有些系统可能无法支持 DirectX11,因此打开了 WARP及 SOFTWARE。


另外,这里其实故意埋了一个提示,观察仔细的人应该能发现:


左图是 GUI 用 label 显示的效果,右图是 Dx11 render 出的 texture。右图显示看上去有些奇怪,是我故意留下的提示。

 

Shader

真正的算法就在这里了。Shader 已经编译为 HLSL 的 bytecode,想要获得算法,首先需要能够找到编译好的 shader 在代码中的位置,然后利用 DirectX 的 D3DDisassemble()反编译

shader,得到 HLSL,从而分析得出真正的算法。反编译代码详见附件。

 

Shader中再次对输入做了判断,要求 3个变量都是 10位的回文数,截取高 5位作为参与算法验证的变量。而真正的算法其实就是一道简单的四元一次方程组,其中一元已设为常数,

a = 14159

a + x + y+ z  = 95028


因此实际是三元一次方程组:{


pi =3

e  = 2

h = 6


, { a ∗ 1 + pi∗x + y −x= 53574

a ∗ 2 + e ∗ y + z − x  = 99009

a∗ 3 + h ∗ z + x − y = 264917

 

x  = 17580

解得:{y =24982

z = 38307


因此正确的序列号为(175800857124982289423830770383),注意回文数。



0x04 总 结

 

这道题正确的解题顺序是:


  • 分析 GUI,找到分析算法的位置是在 Shader 中,排除陷阱算法的干扰。

  • 分析出正则表达式对输入的预处理,合法输入是30 位十进制数字,每10位将作为一个变量参与计算。

  • 反编译 HLSL 字节码拿到 Shader 的汇编。

  • 分析 Shader 汇编,得到真正的算法。

  • 计算三元一次方程组,得到正确的序列号。不知道你做对了吗?


0x05 附 录

 

  • nana C++ Libraryhttp://nanapro.org

  • CrackMe 源代码:见附件。

  • 反编译 HLSLbytecode 的小工具:见附件。

  • 全新安装 Windows732 位下测试通过。


原文链接:

https://bbs.pediy.com/thread-228465.htm

  


第九题  谍战 解题思路


本题解析由看雪论坛 风间仁 原创。


1. 总体逻辑


程序使用的nana库写的界面, 有两个label,一个是显示" Correct ", 一个是显示"Wrong",都在相同的位置, 相同的大小。

 

在textbox的text_changed事件中获取sn,


按"^([[:d:]]{10})([[:d:]]{10})([[:d:]]{10})$"的格式获取三个10位数字,


加锁处理sn(转换为16进制后写入directx的线程参数)


开启一个线程用于directx验证sn及在label处绘制"Correct"/"Wrong"

线程的参数如下:

struct st_dx_param {

   DWORD hThread;

   DWORD dwThreadId;

   HANDLE hEvent;

   DWORD d03;

   HWND hWndParent;

   DWORD d05;

   DWORD d06;

   DWORD d07;

   DWORD d08;

   DWORD d09;

   DWORD d10;

   DWORD d11;

   DWORD d12;

   int X; // 50

   int Y; // 20

   int nWidth; // 200

   int nHeight; // 80

   DWORD d17;

   double rgbSuccess[4]; // 0,128,0,1 green

   double rgbFail[4]; // 255,0,0,1 red

   CRITICAL_SECTION cs;

   DWORD sn0; // 0

   DWORD sn1; // 0

   DWORD sn2; // 0

};


2. nana::textbox(sn的处理及赋值)

// textbox.text_changed的lambda表达式
.text:00402D80                 mov     dword ptr [ebp-16Ch], offset ??_7textbox@nana@@6B@ ; const nana::textbox::`vftable'
...
.text:00402DE3                 mov     dword ptr [ebp-420h], offset x_textbox_text_changed_lambda_vtbl
...
.text:00402E0F                 mov     dword ptr [edi], offset ??_7docker@?$basic_event@Uarg_textbox@nana@@@nana@@6B@ ; const nana::basic_event<nana::arg_textbox>::docker::`vftable'

// x_DoCall是text_changed的处理函数
.rdata:004AB384 x_textbox_text_changed_lambda_vtbl dd offset sub_410C90
.rdata:004AB384                                         ; DATA XREF: wWinMain(x,x,x,x)+B43↑o
.rdata:004AB388                 dd offset sub_410C90
.rdata:004AB38C                 dd offset x_DoCall
.rdata:004AB390                 dd offset sub_410C80
.rdata:004AB394                 dd offset sub_410C50
.rdata:004AB398                 dd offset sub_410C70

// 字符串 -> 整数, 写入st_dx_param
.text:00403528                 call    x_atoi
.text:0040352D                 mov     ecx, [eax]
.text:0040352F                 mov     ecx, [ecx+4]
.text:00403532                 test    byte ptr [ecx+eax+0Ch], 6
.text:00403537                 jnz     short loc_403595
.text:00403539                 lea     eax, [ebp+var_1C]
.text:0040353C                 push    eax
.text:0040353D                 lea     ecx, [ebp+var_1D8]
.text:00403543                 call    x_atoi
.text:00403548                 mov     ecx, [eax]
.text:0040354A                 mov     ecx, [ecx+4]
.text:0040354D                 test    byte ptr [ecx+eax+0Ch], 6
.text:00403552                 jnz     short loc_403595
.text:00403554                 lea     eax, [ebp+sn0]
.text:00403557                 push    eax
.text:00403558                 lea     ecx, [ebp+var_130]
.text:0040355E                 call    x_atoi
.text:00403563                 mov     ecx, [eax]
.text:00403565                 mov     ecx, [ecx+4]
.text:00403568                 test    byte ptr [ecx+eax+0Ch], 6
.text:0040356D                 jnz     short loc_403595
.text:0040356F                 mov     ecx, [esi+8]
.text:00403572                 mov     eax, [ebp+var_18]
.text:00403575                 mov     [ecx+st_dx_param.sn0], eax
.text:0040357B                 mov     ecx, [esi+8]
.text:0040357E                 mov     eax, [ebp+var_1C]
.text:00403581                 mov     [ecx+st_dx_param.sn1], eax
.text:00403587                 mov     ecx, [esi+8]
.text:0040358A                 mov     eax, [ebp+sn0]
.text:0040358D                 mov     [ecx+st_dx_param.sn2], eax


后面好像有一串计算过程及验证, 不过直接patch跳过去, 并不会显示"Correct",所以这里并不是真正的验证点。


3. directx

.text:00403D75                 mov     eax, [esi+30h]
.text:00403D78                 mov     [eax+10h], ecx
.text:00403D7B                 mov     ecx, [esi+30h]
.text:00403D7E                 lea     eax, [ecx+4]
.text:00403D81                 push    eax             ; lpThreadId
.text:00403D82                 push    0               ; dwCreationFlags
.text:00403D84                 push    ecx             ; lpParameter
.text:00403D85                 push    offset x_dx_thread ; lpStartAddress
.text:00403D8A                 push    0               ; dwStackSize
.text:00403D8C                 push    0               ; lpThreadAttributes
.text:00403D8E                 call    ds:CreateThread


将d3d11.h的头文件修改下导入IDA,


这里有3个Directx Shader Bytecode,

__m128d ConstantBufferData[15];


sn放到ConstantBufferData[14]


VertexShader的输入格式:

struct {

   DXGI_FORMAT_R32G32B32_FLOAT     POSITION;

   DXGI_FORMAT_R32G32_FLOAT        TEXCOORD;

   DXGI_FORMAT_R32G32B32A32_FLOAT  COLOR;

};


g_buf_input1的点绘制出来是"绿色背景的Correct!"


g_buf_input2的点绘制出来是"红色背景的Wrong!"

DWORD __stdcall x_dx_thread(st_dx_param *param)

{

   //...

   WNDCLASSEXW a1;

   //...

   RegisterClassExW(&a1);

   HWND hWnd = CreateWindowExW(0, a1.lpszClassName, L"2018CTF@pediy.com", 0x50000000,

       param->X,

       param->Y,

       param->nWidth,

       param->nHeight,

       param->hWndParent,

       0, GetWindowLongW(param->hWndParent, GWL_HINSTANCE), 0);

   ShowWindow(hWnd, SW_SHOW);

   //...

   RECT rect;

   GetClientRect(param->hWndParent, &rect);

   GetWindowRect(param->hWndParent, &rect);

   //...

   float rgbSuccess[4];

   float rgbFail[4];

   memcpy(rgbSuccess, param->rgbSuccess, 16);

   memcpy(rgbFail, param->rgbFail, 16);



   //...

   D3D_DRIVER_TYPE DriverTypes[3];

   DriverTypes[0] = D3D_DRIVER_TYPE_HARDWARE;

   DriverTypes[1] = D3D_DRIVER_TYPE_WARP;

   DriverTypes[2] = D3D_DRIVER_TYPE_SOFTWARE;



   D3D_FEATURE_LEVEL FeatureLevels[3];

   FeatureLevels[0] = D3D_FEATURE_LEVEL_11_0;

   FeatureLevels[1] = D3D_FEATURE_LEVEL_10_1;

   FeatureLevels[2] = D3D_FEATURE_LEVEL_10_0;



   D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_0;



   DXGI_SWAP_CHAIN_DESC SwapChainDesc;

   SwapChainDesc.BufferDesc.Width = param->nWidth;

   SwapChainDesc.BufferDesc.Height = param->nHeight;

   SwapChainDesc.OutputWindow = hWnd;

   SwapChainDesc.BufferCount = 1;

   SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

   SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60;

   SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1;

   SwapChainDesc.BufferUsage = 32;

   SwapChainDesc.SampleDesc.Count = 1;

   SwapChainDesc.SampleDesc.Quality = 0;

   SwapChainDesc.Windowed = 1;

   IDXGISwapChain *SwapChain;

   ID3D11Device *Device;

   ID3D11DeviceContext *DeviceContext;

   D3D11CreateDeviceAndSwapChain(0, DriverTypes[i], 0, 0, FeatureLevels, 3, 7, &SwapChainDesc, &SwapChain, &Device, &FeatureLevel, &DeviceContext);



   ID3D11Texture2D *Surface;

   D3D11_TEXTURE2D_DESC Desc;

   ID3D11RenderTargetView *RenderTargetView;

   SwapChain->lpVtbl->GetBuffer(SwapChain, 0, &IID_D3D11Texture2D, &Surface);

   Surface->lpVtbl->GetDesc(Surface, &Desc);

   Device->lpVtbl->CreateRenderTargetView(Device, Surface, 0, &RenderTargetView);



   ID3D11Texture2D *Resource0;

   ID3D11Texture2D *Resource1;

   Desc.Usage = 0;

   Desc.BindFlags = D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE;

   Desc.CPUAccessFlags = 0;

   Desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;

   Device->lpVtbl->CreateTexture2D(Device, &Desc, 0, &Resource0);

   Device->lpVtbl->CreateTexture2D(Device, &Desc, 0, &Resource1);

   ID3D11RenderTargetView *RenderTargetViewSuccess;

   ID3D11RenderTargetView *RenderTargetViewFail;

   Device->lpVtbl->CreateRenderTargetView(Device, Resource0, 0, &RenderTargetViewSuccess);

   Device->lpVtbl->CreateRenderTargetView(Device, Resource1, 0, &RenderTargetViewFail);



   D3D11_SHADER_RESOURCE_VIEW_DESC ResourceViewDesc;

   ResourceViewDesc.Format = Desc.Format;

   ResourceViewDesc.Texture2D.MostDetailedMip = 0;

   ResourceViewDesc.Texture2D.MipLevels = -1;

   ResourceViewDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;

   ID3D11ShaderResourceView *ShaderResourceViewSuccess;

   ID3D11ShaderResourceView *ShaderResourceViewFail;

   Device->lpVtbl->CreateShaderResourceView(Device, Resource0, &ResourceViewDesc, &ShaderResourceViewSuccess);

   Device->lpVtbl->CreateShaderResourceView(Device, Resource1, &ResourceViewDesc, &ShaderResourceViewFail);



   char g_buf_VertexShader[1308];

   char g_buf_PixelShader0[496];

   char g_buf_PixelShader1[3108];

   D3D11_INPUT_ELEMENT_DESC InputElementDescs[3];

   InputElementDescs[0].SemanticName = "POSITION";

   InputElementDescs[0].SemanticIndex = 0;

   InputElementDescs[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;

   InputElementDescs[0].InputSlot = 0;

   InputElementDescs[0].AlignedByteOffset = 0;

   InputElementDescs[0].InputSlotClass = 0;

   InputElementDescs[0].InstanceDataStepRate = 0;

   InputElementDescs[1].SemanticName = "TEXCOORD";

   InputElementDescs[1].SemanticIndex = 0;

   InputElementDescs[1].Format = DXGI_FORMAT_R32G32_FLOAT;

   InputElementDescs[1].InputSlot = 0;

   InputElementDescs[1].AlignedByteOffset = 12;

   InputElementDescs[1].InputSlotClass = 0;

   InputElementDescs[1].InstanceDataStepRate = 0;

   InputElementDescs[2].SemanticName = "COLOR";

   InputElementDescs[2].SemanticIndex = 0;

   InputElementDescs[2].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;

   InputElementDescs[2].InputSlot = 0;

   InputElementDescs[2].AlignedByteOffset = 20;

   InputElementDescs[2].InputSlotClass = 0;

   InputElementDescs[2].InstanceDataStepRate = 0;

   ID3D11VertexShader *VertexShader;

   ID3D11InputLayout *InputLayout;

   ID3D11PixelShader *PixelShader0;

   ID3D11PixelShader *PixelShader1;

   Device->lpVtbl->CreateVertexShader(Device, g_buf_VertexShader, 1308, 0, &VertexShader);

   Device->lpVtbl->CreateInputLayout(Device, InputElementDescs, 3, g_buf_VertexShader, 1308, &InputLayout);

   Device->lpVtbl->CreatePixelShader(Device, g_buf_PixelShader0, 496, 0, &PixelShader0);

   Device->lpVtbl->CreatePixelShader(Device, g_buf_PixelShader1, 3108, 0, &PixelShader1);



   D3D11_SAMPLER_DESC SamplerDesc;

   SamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;

   SamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;

   SamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;

   SamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;

   SamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;

   SamplerDesc.MinLOD = 0;

   SamplerDesc.MaxLOD = FLT_MAX;

   ID3D11SamplerState *Sampler;

   Device->lpVtbl->CreateSamplerState(Device, &SamplerDesc, &Sampler);



   char g_buf_input0[144];

   char g_buf_input1[63936];

   char g_buf_input2[62028];

   __int16 g_buf_indice0[6];

   __int16 g_buf_indice1[5283];

   __int16 g_buf_indice2[5142];

   D3D11_SUBRESOURCE_DATA InitialData;

   D3D11_BUFFER_DESC BufferDesc;

   ID3D11Buffer *VertexBuffer0;

   ID3D11Buffer *VertexBuffer1;

   ID3D11Buffer *VertexBuffer2;

   ID3D11Buffer *IndexBuffer0;

   ID3D11Buffer *IndexBuffer1;

   ID3D11Buffer *IndexBuffer2;

   ID3D11Buffer *ConstantBuffer;



   //...

   BufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;

   InitialData.pSysMem = g_buf_input0;

   BufferDesc.ByteWidth = sizeof(g_buf_input0);

   Device->lpVtbl->CreateBuffer(Device, &BufferDesc, &InitialData, &VertexBuffer0);

   //...

   InitialData.pSysMem = g_buf_input1;

   BufferDesc.ByteWidth = sizeof(g_buf_input1);

   Device->lpVtbl->CreateBuffer(Device, &BufferDesc, &InitialData, &VertexBuffer1);

   //...

   InitialData.pSysMem = g_buf_input2;

   BufferDesc.ByteWidth = sizeof(g_buf_input2);

   Device->lpVtbl->CreateBuffer(Device, &BufferDesc, &InitialData, &VertexBuffer2);



   //...

   BufferDesc.BindFlags =  D3D11_BIND_INDEX_BUFFER;

   InitialData.pSysMem = g_buf_indice0;

   BufferDesc.ByteWidth = sizeof(g_buf_indice0);

   Device->lpVtbl->CreateBuffer(Device, &BufferDesc, &InitialData, &IndexBuffer0);

   //...

   InitialData.pSysMem = g_buf_indice1;

   BufferDesc.ByteWidth = sizeof(g_buf_indice1);

   Device->lpVtbl->CreateBuffer(Device, &BufferDesc, &InitialData, &IndexBuffer1);

   //...

   InitialData.pSysMem = g_buf_indice2;

   BufferDesc.ByteWidth = sizeof(g_buf_indice2);

   Device->lpVtbl->CreateBuffer(Device, &BufferDesc, &InitialData, &IndexBuffer2);

   

   //...

   BufferDesc.ByteWidth = 240;

   BufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;

   Device->lpVtbl->CreateBuffer(Device, &BufferDesc, 0, &ConstantBuffer);



   __m128d ConstantBufferData[15];

   // ... ConstantBufferData init

   

   D3D11_VIEWPORT Viewport;

   Viewport.MinDepth = 0.0;

   Viewport.MaxDepth = 1.0;

   Viewport.TopLeftX = 0.0;

   Viewport.TopLeftY = 0.0;

   Viewport.Width = param->nWidth;

   Viewport.Height = param->nHeight;

   UINT Stride = 36;

   UINT Offset = 0;



   // g_buf_input1 -> VertexShader -> PixelShader0

   DeviceContext->lpVtbl->UpdateSubresource(DeviceContext, ConstantBuffer, 0, 0, ConstantBufferData, 0, 0);

   DeviceContext->lpVtbl->ClearRenderTargetView(DeviceContext, RenderTargetViewSuccess, rgbSuccess);

   DeviceContext->lpVtbl->OMSetRenderTargets(DeviceContext, 1, &RenderTargetViewSuccess, 0);

   DeviceContext->lpVtbl->RSSetViewports(DeviceContext, 1, &Viewport);

   DeviceContext->lpVtbl->IASetVertexBuffers(DeviceContext, 0, 1, &VertexBuffer1, &Stride, &Offset);

   DeviceContext->lpVtbl->IASetIndexBuffer(DeviceContext, IndexBuffer1, DXGI_FORMAT_R16_UINT, 0);

   DeviceContext->lpVtbl->IASetInputLayout(DeviceContext, InputLayout);

   DeviceContext->lpVtbl->IASetPrimitiveTopology(DeviceContext, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

   DeviceContext->lpVtbl->VSSetShader(DeviceContext, VertexShader, 0, 0);

   DeviceContext->lpVtbl->VSSetConstantBuffers(DeviceContext, 0, 1, &ConstantBuffer);

   DeviceContext->lpVtbl->PSSetShader(DeviceContext, PixelShader0, 0, 0);

   DeviceContext->lpVtbl->PSSetConstantBuffers(DeviceContext, 0, 1, &ConstantBuffer);

   DeviceContext->lpVtbl->PSSetSamplers(DeviceContext, 0, 1, &Sampler);

   DeviceContext->lpVtbl->DrawIndexed(DeviceContext, ARRAYSIZE(g_buf_indice1), 0, 0);



   // g_buf_input2 -> VertexShader -> PixelShader0

   DeviceContext->lpVtbl->GenerateMips(DeviceContext, ShaderResourceViewSuccess);

   DeviceContext->lpVtbl->UpdateSubresource(DeviceContext, ConstantBuffer, 0, 0, ConstantBufferData, 0, 0);

   DeviceContext->lpVtbl->ClearRenderTargetView(DeviceContext, RenderTargetViewFail, rgbFail);

   DeviceContext->lpVtbl->OMSetRenderTargets(DeviceContext, 1, &RenderTargetViewFail, 0);

   DeviceContext->lpVtbl->RSSetViewports(DeviceContext, 1, &Viewport);

   DeviceContext->lpVtbl->IASetVertexBuffers(DeviceContext, 0, 1, &VertexBuffer2, &Stride, &Offset);

   DeviceContext->lpVtbl->IASetIndexBuffer(DeviceContext, IndexBuffer2, DXGI_FORMAT_R16_UINT, 0);

   DeviceContext->lpVtbl->IASetInputLayout(DeviceContext, InputLayout);

   DeviceContext->lpVtbl->IASetPrimitiveTopology(DeviceContext, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

   DeviceContext->lpVtbl->VSSetShader(DeviceContext, VertexShader, 0, 0);

   DeviceContext->lpVtbl->VSSetConstantBuffers(DeviceContext, 0, 1, &ConstantBuffer);

   DeviceContext->lpVtbl->PSSetShader(DeviceContext, PixelShader0, 0, 0);

   DeviceContext->lpVtbl->PSSetConstantBuffers(DeviceContext, 0, 1, &ConstantBuffer);

   DeviceContext->lpVtbl->PSSetSamplers(DeviceContext, 0, 1, &Sampler);

   DeviceContext->lpVtbl->DrawIndexed(DeviceContext, ARRAYSIZE(g_buf_indice2), 0, 0);

   DeviceContext->lpVtbl->GenerateMips(DeviceContext, ShaderResourceViewFail);



   //...

   while ( WaitForSingleObjectEx(param->hEvent, 0, 0) == WAIT_TIMEOUT )

   {

       MSG msg;

       if (PeekMessageW(&msg, 0, 0, 0, 1))

       {

           TranslateMessage(&msg);

           DispatchMessageW(&msg);

       }

       EnterCriticalSection(&param->cs);

       ConstantBufferData[14].m128d_f32[0] = param->sn0;

       ConstantBufferData[14].m128d_f32[1] = param->sn1;

       ConstantBufferData[14].m128d_f32[2] = param->sn2;

       LeaveCriticalSection(&param->cs);



       //...

       // g_buf_input0 -> VertexShader -> PixelShader1

       DeviceContext->lpVtbl->UpdateSubresource(DeviceContext, ConstantBuffer, 0, 0, ConstantBufferData, 0, 0);

       DeviceContext->lpVtbl->ClearRenderTargetView(DeviceContext, RenderTargetView, rgbBlack);

       DeviceContext->lpVtbl->OMSetRenderTargets(DeviceContext, 1, &RenderTargetView, 0);

       DeviceContext->lpVtbl->RSSetViewports(DeviceContext, 1, &Viewport);

       DeviceContext->lpVtbl->IASetVertexBuffers(DeviceContext, 0, 1, &VertexBuffer0, &Stride, &Offset);

       DeviceContext->lpVtbl->IASetIndexBuffer(DeviceContext, IndexBuffer0, DXGI_FORMAT_R16_UINT, 0);

       DeviceContext->lpVtbl->IASetInputLayout(DeviceContext, InputLayout);

       DeviceContext->lpVtbl->IASetPrimitiveTopology(DeviceContext, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

       DeviceContext->lpVtbl->VSSetShader(DeviceContext, VertexShader, 0, 0);

       DeviceContext->lpVtbl->VSSetConstantBuffers(DeviceContext, 0, 1, &ConstantBuffer);

       DeviceContext->lpVtbl->PSSetShader(DeviceContext, PixelShader1, 0, 0);

       DeviceContext->lpVtbl->PSSetConstantBuffers(DeviceContext, 0, 1, &ConstantBuffer);

       DeviceContext->lpVtbl->PSSetShaderResources(DeviceContext, 0, 1, &ShaderResourceViewSuccess);

       DeviceContext->lpVtbl->PSSetShaderResources(DeviceContext, 1, 1, &ShaderResourceViewFail);

       DeviceContext->lpVtbl->PSSetSamplers(DeviceContext, 0, 1, &Sampler);

       DeviceContext->lpVtbl->DrawIndexed(DeviceContext, 6, 0, 0);



       SwapChain->lpVtbl->Present(SwapChain, 0, 0);

       Sleep(2);

   }

   //...

   return 0;


将3个bytecode提取出来, 用fxdis反汇编下。


VertexShader:

# DXBC chunk  0: RDEF offset 52 size 352

# DXBC chunk  1: ISGN offset 412 size 104

# DXBC chunk  2: OSGN offset 524 size 108

# DXBC chunk  3: SHDR offset 640 size 536

# DXBC chunk  4: STAT offset 1184 size 116

vs_4_0

dcl_constant_buffer cb0[12].xyzw, immediateIndexed

dcl_input v0.xyzw

dcl_input v1.xy

dcl_input v2.xyzw

dcl_output_siv o0.xyzw, position

dcl_output o1.xy

dcl_output o2.xyzw

dcl_temps 2

dp4 r0.x, v0.xyzw, cb0[8].xyzw

dp4 r0.y, v0.xyzw, cb0[9].xyzw

dp4 r0.z, v0.xyzw, cb0[10].xyzw

dp4 r0.w, v0.xyzw, cb0[11].xyzw

dp4 r1.x, r0.xyzw, cb0[0].xyzw

dp4 r1.y, r0.xyzw, cb0[1].xyzw

dp4 r1.z, r0.xyzw, cb0[2].xyzw

dp4 r1.w, r0.xyzw, cb0[3].xyzw

dp4 o0.x, r1.xyzw, cb0[4].xyzw

dp4 o0.y, r1.xyzw, cb0[5].xyzw

dp4 o0.z, r1.xyzw, cb0[6].xyzw

dp4 o0.w, r1.xyzw, cb0[7].xyzw

mov o1.xy, v1.xyxx

mov o2.xyzw, v2.xyzw

ret


PixelShader0

# DXBC chunk  0: RDEF offset 52 size 80

#
DXBC chunk  1: ISGN offset 140 size 108

#
DXBC chunk  2: OSGN offset 256 size 44

#
DXBC chunk  3: SHDR offset 308 size 56

#
DXBC chunk  4: STAT offset 372 size 116

ps_4_0

dcl_input_ps linear v2.xyzw

dcl_output o0.xyzw

mov o0.xyzw, v2.xyzw

ret


PixelShader1(这个是验证sn的地方, 成功则绘制"Correct", 失败则绘制"Wrong"):

# DXBC chunk  0: RDEF offset 52 size 468

# DXBC chunk  1: ISGN offset 528 size 108

# DXBC chunk  2: OSGN offset 644 size 44

# DXBC chunk  3: SHDR offset 696 size 2280

# DXBC chunk  4: STAT offset 2984 size 116

ps_4_0

dcl_constant_buffer cb0[15].xyzw, immediateIndexed

dcl_sampler sampler[0]

dcl_resource_texture2d resource[0]

dcl_resource_texture2d resource[1]

dcl_input_ps linear v1.xy

dcl_output o0.xyzw

dcl_temps 4

ine r0.xyz, cb0[14].xyzx, l(0, 0, 0, 0)

and r0.x, r0.y, r0.x

and r0.x, r0.z, r0.x

ult r0.y, l(1000000000), cb0[14].x

and r0.x, r0.y, r0.x

ult r0.yz, cb0[14].xxyx, cb0[14].yyzy

and r0.x, r0.y, r0.x

and r0.x, r0.z, r0.x

ult r0.y, cb0[14].z, l(4294967295)

and r0.x, r0.y, r0.x

udiv r0.yzw, null, cb0[14].zzxy, l(0, 100000, 100000, 100000)

imad r1.xyz, r0.zwyz, l(-100000, -100000, -100000, 0), cb0[14].xyzx

udiv r2.x, r3.x, r0.z, l(10)

udiv null, r1.w, r2.x, l(10)

udiv r2.xyzw, null, r0.zzzw, l(100, 1000, 10000, 100)

udiv null, r2.xyzw, r2.xyzw, l(10, 10, 10, 10)

imul null, r1.w, r1.w, l(1000)

imad r1.w, r3.x, l(10000), r1.w

imad r1.w, r2.x, l(100), r1.w

imad r1.w, r2.y, l(10), r1.w

iadd r1.w, r2.z, r1.w

ieq r1.x, r1.x, r1.w

and r0.x, r0.x, r1.x

udiv r1.x, r2.x, r0.w, l(10)

udiv null, r1.x, r1.x, l(10)

udiv r3.xyzw, null, r0.wwyy, l(1000, 10000, 100, 1000)

udiv null, r3.xyzw, r3.xyzw, l(10, 10, 10, 10)

imul null, r1.x, r1.x, l(1000)

imad r1.x, r2.x, l(10000), r1.x

imad r1.x, r2.w, l(100), r1.x

imad r1.x, r3.x, l(10), r1.x

iadd r1.x, r3.y, r1.x

ieq r1.x, r1.y, r1.x

and r0.x, r0.x, r1.x

udiv r1.x, r2.x, r0.y, l(10)

udiv r1.y, null, r0.y, l(10000)

udiv null, r1.xy, r1.xyxx, l(10, 10, 0, 0)

imul null, r1.x, r1.x, l(1000)

imad r1.x, r2.x, l(10000), r1.x

imad r1.x, r3.z, l(100), r1.x

imad r1.x, r3.w, l(10), r1.x

iadd r1.x, r1.y, r1.x

ieq r1.x, r1.z, r1.x

and r0.x, r0.x, r1.x

movc r0.yzw, r0.xxxx, r0.yyzw, cb0[14].zzxy

iadd r1.x, r0.w, r0.z

iadd r1.x, r0.y, r1.x

iadd r1.x, r1.x, l(14159)

ieq r1.x, r1.x, l(95028)

and r0.x, r0.x, r1.x

imad r1.xy, l(3, 6, 0, 0), r0.zyzz, r0.wzww

iadd r1.xy, r1.xyxx, l(14159, 42477, 0, 0)

iadd r1.xy, -r0.ywyy, r1.xyxx

ieq r1.xy, r1.xyxx, l(53574, 264917, 0, 0)

and r0.x, r0.x, r1.x

ishl r0.w, r0.w, l(1)

iadd r0.y, r0.w, r0.y

iadd r0.y, r0.y, l(28318)

iadd r0.y, -r0.z, r0.y

ieq r0.y, r0.y, l(99009)

and r0.x, r0.y, r0.x

and r0.x, r1.y, r0.x

if_nz r0.x

sample o0.xyzw, v1.xyxx, resource[0].xyzw, sampler[0]

ret

else

sample o0.xyzw, v1.xyxx, resource[1].xyzw, sampler[0]

ret

endif

ret


参考: 


_https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-sm4-asm

sn0=x

sn1=y

sn2=z



0xFFFFFFFF > z > y > x > 1000000000



r0_y = z/100000

r0_z = x/100000

r0_w = y/100000

r1_x = r0_z * (-100000) + x = x % 100000

r1_y = r0_w * (-100000) + y = y % 100000

r1_z = r0_y * (-100000) + z = z % 100000



r2_x = r0_z / 10

r3_x = r0_z % 10

r1_w = r2_x % 10

r2_x = r0_z / 100

r2_y = r0_z / 1000

r2_z = r0_z / 10000

r2_w = r0_w / 100

r2_x = r2_x % 10

r2_y = r2_y % 10

r2_z = r2_z % 10

r2_w = r2_w % 10

r1_w = r1_w * 1000

r1_w = r3_x * 10000 + r1_w

r1_w = r2_x * 100 + r1_w

r1_w = r2_y * 10 + r1_w

r1_w = r2_z + r1_w

r1_x  == r1_w



r1_x = r0_w / 10

r2_x = r0_w % 10

r1_x = r1_x % 10

r3_x = r0_w / 1000

r3_y = r0_w / 10000

r3_z = r0_y / 100

r3_w = r0_y / 1000

r3_x = r3_x % 10

r3_y = r3_y % 10

r3_z = r3_z % 10

r3_w = r3_w % 10

r1_x = r1_x * 1000

r1_x = r2_x * 10000 + r1_x

r1_x = r2_w * 100 + r1_x

r1_x = r3_x * 10 + r1_x

r1_x = r3_y + r1_x

r1_y == r1_x



r1_x = r0_y / 10

r2_x = r0_y % 10

r1_y = r0_y / 10000

r1_x = r1_x % 10

r1_y = r1_y % 10

r1_x = r1_x * 1000

r1_x = r2_x * 10000 + r1_x

r1_x = r3_z * 100 + r1_x

r1_x = r3_w * 10 + r1_x

r1_x = r1_y + r1_x

r1_z == r1_x



r1_x = r0_w + r0_z

r1_x = r0_y + r1_x

r1_x = r1_x + 14159

r1_x == 95028



r1_x = 3 * r0_z + r0_w

r1_y = 6 * r0_y + r0_z

r1_x = r1_x + 14159

r1_y = r1_y + 42477

r1_x = -r0_y + r1_x

r1_y = -r0_w + r1_y

r1_x == 53574

r1_y == 264917



r0_w = r0_w << 1

r0_y = r0_w + r0_y

r0_y = r0_y + 28318

r0_y = -r0_z + r0_y

r0_y == 99009


将上述代码化简下:

sn0=x

sn1=y

sn2=z



0xFFFFFFFF > z > y > x > 1000000000



r0_y = z/100000

r0_z = x/100000

r0_w = y/100000

r1_x = x % 100000

r1_y = y % 100000

r1_z = z % 100000



r1_x == ((r0_z / 10000) % 10) + ((r0_z / 1000) % 10) * 10 + ((r0_z / 100) % 10) * 100 + (r0_z % 10) * 10000 + ((r0_z / 10) % 10) * 1000

r1_y == ((r0_w / 10000) % 10) + ((r0_w / 1000) % 10) * 10 + ((r0_w / 100) % 10) * 100 + (r0_w % 10) * 10000 + ((r0_w / 10) % 10) * 1000

r1_z == ((r0_y / 10000) % 10) + ((r0_y / 1000) % 10) * 10 + ((r0_y / 100) % 10) * 100 + (r0_y % 10) * 10000 + (((r0_y / 10) % 10) * 1000)

95028 == r0_w + r0_z + r0_y + 14159

53574 == -r0_y + 3 * r0_z + r0_w + 14159

264917 == -r0_w + 6 * r0_y + r0_z + 42477

99009 == -r0_z + r0_w * 2 + r0_y + 28318


直接用z3算出结果,得到


sn: 175800857124982289423830770383

[r0_z = 17580,

r0_w = 24982,

r1_z = 70383,

r1_y = 28942,

r1_x = 8571,

r0_y = 38307]


原文链接:

https://bbs.pediy.com/thread-248467.htm






第十题【侠义双雄】正在火热进行中


第10题/共15题


《侠义双雄》将于12月21日中午12:00结束


赶紧参与进来吧~!


热门图书推荐:

 立即购买!



合作伙伴 

腾讯安全应急响应中心 

TSRC,腾讯安全的先头兵,肩负腾讯公司安全漏洞、黑客入侵的发现和处理工作。这是个没有硝烟的战场,我们与两万多名安全专家并肩而行,捍卫全球亿万用户的信息、财产安全。一直以来,我们怀揣感恩之心,努力构建开放的TSRC交流平台,回馈安全社区。未来,我们将继续携手安全行业精英,探索互联网安全新方向,建设互联网生态安全,共铸“互联网+”新时代。






- End -


公众号ID:ikanxue

官方微博:看雪安全

商务合作:wsc@kanxue.com


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存