看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路

Editor發表於2018-12-19


看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路


第九題《諜戰》在今天(12月19日)中午12:00 結束攻擊。


只有五支團隊在這場邏輯嚴謹,情節緊張,風起雲湧的“諜戰”中存活了下來。本題出題團隊GPUber 此次在防守方排名位居第二。


看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路


最新賽況戰況一覽


第九題之後,攻擊方最新排名情況如下:


看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路


中午放題搬磚狗哭哭 的第一名寶座暫時無人撼動!Acehub從第6名上升至第4名,雨落星辰上升1名,至第5名。n0body 突進前10位。


或許,劇情會出乎所有人的預料,會有第三支團隊衝出重圍讓所有人大跌眼鏡嗎?


看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路



第九題 點評


crownless:

解開“諜戰”此題需要排除陷阱演算法的干擾,方法是分析GUI並找到分析演算法的位置是在Shader中。接著,此題考查了組合語言以及三元一次方程組。因此,解開此題需要較為全面的計算機和數學基礎。



第九題 出題團隊簡介


出題團隊: GPUber


看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路


第九題 設計思路


由看雪論壇supercolin 原創


看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路



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:


看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路


然後,將 mesh 匯出為 wavefront obj 格式的 3D 模型,如下:


看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路


最後,對頂點及索引資料稍作處理,便於之後的 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。


另外,這裡其實故意埋了一個提示,觀察仔細的人應該能發現:


看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路


左圖是 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



第九題  諜戰 解題思路


本題解析由看雪論壇風間仁原創。


看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路


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: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

後面好像有一串計算過程及驗證, 不過直接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_FLOATCOLOR;
 
};
 
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(¶m->cs);
 
ConstantBufferData[14].m128d_f32[0] = param->sn0;
 
ConstantBufferData[14].m128d_f32[1] = param->sn1;
 
ConstantBufferData[14].m128d_f32[2] = param->sn2;
 
LeaveCriticalSection(¶m->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結束

趕緊參與進來吧~!


合作伙伴 

看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路

騰訊安全應急響應中心 

TSRC,騰訊安全的先頭兵,肩負騰訊公司安全漏洞、駭客入侵的發現和處理工作。這是個沒有硝煙的戰場,我們與兩萬多名安全專家並肩而行,捍衛全球億萬使用者的資訊、財產安全。一直以來,我們懷揣感恩之心,努力構建開放的TSRC交流平臺,回饋安全社群。未來,我們將繼續攜手安全行業精英,探索網際網路安全新方向,建設網際網路生態安全,共鑄“網際網路+”新時代。

看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路

看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路


轉載請註明:轉自看雪學院


更多閱讀:






相關文章