看雪CTF.TSRC 2018 團隊賽 第九題『諜戰』 解題思路
第九題《諜戰》在今天(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: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結束
趕緊參與進來吧~!
合作伙伴
騰訊安全應急響應中心
TSRC,騰訊安全的先頭兵,肩負騰訊公司安全漏洞、駭客入侵的發現和處理工作。這是個沒有硝煙的戰場,我們與兩萬多名安全專家並肩而行,捍衛全球億萬使用者的資訊、財產安全。一直以來,我們懷揣感恩之心,努力構建開放的TSRC交流平臺,回饋安全社群。未來,我們將繼續攜手安全行業精英,探索網際網路安全新方向,建設網際網路生態安全,共鑄“網際網路+”新時代。
轉載請註明:轉自看雪學院
更多閱讀:
相關文章
- 看雪CTF.TSRC 2018 團隊賽 第七題 『魔法森林』 解題思路2018-12-23
- 看雪CTF.TSRC 2018 團隊賽 第一題 『初世紀』 解題思路2018-12-23
- 看雪CTF.TSRC 2018 團隊賽 第二題 『半加器』 解題思路2018-12-23
- 看雪CTF.TSRC 2018 團隊賽 第五題 『交響曲』 解題思路2018-12-23
- 看雪CTF.TSRC 2018 團隊賽 第六題 『追凶者也』 解題思路2018-12-23
- 看雪CTF.TSRC 2018 團隊賽 第八題 『二向箔』 解題思路2018-12-23
- 看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路2018-12-21
- 看雪CTF.TSRC 2018 團隊賽 第三題 『七十二疑冢』 解題思路2018-12-23
- 看雪CTF.TSRC 2018 團隊賽 第四題 『盜夢空間』 解題思路2018-12-23
- 看雪CTF.TSRC 2018 團隊賽 第十一題『伊甸園』 解題思路2018-12-23
- 看雪CTF.TSRC 2018 團隊賽 第十五題『 密碼風雲』 解題思路2019-01-02密碼
- 看雪CTF.TSRC 2018 團隊賽 第十四題『 你眼中的世界』 解題思路2018-12-29
- 看雪CTF.TSRC 2018 團隊賽 第十二題『移動迷宮』 解題思路2018-12-25
- 看雪CTF.TSRC 2018 團隊賽 第十三題『 機器人歷險記』 解題思路2018-12-27機器人
- 看雪CTF.TSRC 2018 團隊賽 獲獎名單公示2019-01-02
- 看雪·深信服 2021 KCTF 春季賽 | 第九題設計思路及解析2021-05-28
- 看雪·眾安 2021 KCTF 秋季賽 | 第九題設計思路及解析2021-12-09
- 看雪.騰訊TSRC 2017 CTF 秋季賽 第九題點評及解析思路2017-11-13
- 看雪.紐盾 KCTF 2019 Q3 | 第九題點評及解題思路2019-10-08
- 看雪.紐盾 KCTF 2019 Q2 | 第九題點評及解題思路2019-07-04
- 看雪.萬能鑰匙 CTF 2017第一題 WannaLOL 解題思路2017-06-29
- 看雪·深信服 2021 KCTF 春季賽 | 第七題設計思路及解析2021-05-25
- 看雪·深信服 2021 KCTF 春季賽 | 第八題設計思路及解析2021-05-25
- 看雪·深信服 2021 KCTF 春季賽 | 第四題設計思路及解析2021-05-17
- 看雪·深信服 2021 KCTF 春季賽 | 第五題設計思路及解析2021-05-17
- 看雪·深信服 2021 KCTF 春季賽 | 第六題設計思路及解析2021-05-21
- 看雪·深信服 2021 KCTF 春季賽 | 第二題設計思路及解析2021-05-12
- 看雪·深信服 2021 KCTF 春季賽 | 第三題設計思路及解析2021-05-14
- 看雪·深信服 2021 KCTF 春季賽 | 第十題設計思路及解析2021-05-31
- 看雪·眾安 2021 KCTF 秋季賽 | 第十題設計思路及解析2021-12-16
- 看雪·眾安 2021 KCTF 秋季賽 | 第七題設計思路及解析2021-12-03
- 看雪·眾安 2021 KCTF 秋季賽 | 第五題設計思路及解析2021-11-29
- 看雪·眾安 2021 KCTF 秋季賽 | 第三題設計思路及解析2021-11-22
- 看雪·眾安 2021 KCTF 秋季賽 | 第六題設計思路及解析2021-12-01
- 看雪·眾安 2021 KCTF 秋季賽 | 第四題設計思路及解析2021-11-25
- 看雪.騰訊TSRC 2017 CTF 秋季賽 第二題點評及解析思路2017-10-28
- 看雪.騰訊TSRC 2017 CTF 秋季賽 第三題點評及解析思路2017-10-30
- 看雪.騰訊TSRC 2017 CTF 秋季賽 第七題點評及解析思路2017-11-07