首页
论坛
专栏
课程

[原创]看雪京东2018CTF第10题

2018-7-6 12:11 2240

[原创]看雪京东2018CTF第10题

ccfer
13
2018-7-6 12:11
2240
这题最大收获就是学习了一下DirectX HLSL,那些amp的函数我也没查到参数,只能无奈的随便猜猜了

验证流程都在这里:
.text:004035C0                 call    sub_401DF0               //输入转换base64
.text:004035C5                 call    sub_401E80               //一些初始化(seed/表/矩阵)
.text:004035CA                 call    @T0@0                    //Shader Model 5 Assembly (DirectX HLSL)
.text:004035CF                 call    @C0@0                    //没分析,直接单字节穷举,然后查表
.text:004035D4                 call    @T1@0                    //这个fork函数调试难受,容易卡住,最后利用最近学到的输出反馈给输入,很快发现了周期性,然后就好办了
.text:004035D9                 call    @C1@0                    //没分析,直接单字节穷举,然后查表
.text:004035DE                 call    @T2@0                    //没分析透彻,仿佛看到了傅里叶变换的味道,直接晚上开机穷举,早上起来出结果了

大部分时间都花在研究那个T0中那个HLSL验证上了
执行文件中有两段HLSL,偏移40102Ch处长度4CCh,偏移401530h处长度714h

可以直接用D3D反汇编:
void test_10_decompile(BYTE *dxbc_ptr,DWORD len)
{
        HMODULE hDxd;
        DWORD rv = 0;
        DWORD blob[0x400];
        DWORD D3DCreateBlob;
        DWORD D3DDisassemble;

        hDxd = LoadLibrary("D3dcompiler_47.dll");

        if (hDxd)
        {
                D3DCreateBlob = (DWORD)GetProcAddress(hDxd,"D3DCreateBlob");
                D3DDisassemble = (DWORD)GetProcAddress(hDxd,"D3DDisassemble");
                if (D3DDisassemble)
                {
                        rv = ((DWORD (__stdcall *)(DWORD,DWORD *))D3DCreateBlob)(0x400,&blob[0]);
                        rv = ((DWORD (__stdcall *)(BYTE *,DWORD,DWORD,char *,DWORD *))D3DDisassemble)(dxbc_ptr,len,0,"",&blob[0]);
                        //返回的反汇编数据在blob结构中,我直接内存抓出来了
                }
        }
}


偏移40102Ch处第一段:
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Buffer Definitions: 
//
// cbuffer CB_1
// {
//
//   uint _const_buffer_1[28];          // Offset:    0 Size:   436
//
// }
//
//
// Resource Bindings:
//
// Name                                 Type  Format         Dim      HLSL Bind  Count
// ------------------------------ ---------- ------- ----------- -------------- ------
// _GV_buffer_rw_0                       UAV    byte         r/w             u0      1 
// _GV_buffer_rw_1                       UAV    byte         r/w             u1      1 
// CB_1                              cbuffer      NA          NA            cb1      1 
//
//
//
// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Input
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Output
cs_5_0
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB1[24], immediateIndexed
dcl_uav_raw u0
dcl_uav_raw u1
dcl_input vThreadID.xyz
dcl_temps 2
dcl_thread_group 32, 8, 1
imul [precise(x)] null, r0.x, vThreadID.z, cb1[0].x
imad [precise(x)] r0.x, vThreadID.y, cb1[1].x, r0.x
iadd [precise(x)] r0.x, r0.x, vThreadID.x
ult [precise(y)] r0.y, r0.x, cb1[2].x
if_nz r0.y
  udiv [precise(x)] r0.x, r1.x, r0.x, cb1[4].x
  iadd [precise(y)] r0.y, r1.x, cb1[21].x
  iadd [precise(y)] r0.y, r0.y, cb1[23].x
  ishl [precise(y)] r0.y, r0.y, l(2)
  ld_raw_indexable [precise(y)](raw_buffer)(mixed,mixed,mixed,mixed) r0.y, r0.y, u1.xxxx
  ushr [precise(y)] r0.y, r0.y, r0.x
  and [precise(y)] r0.y, r0.y, l(1)
  imad [precise(x)] r0.x, cb1[7].x, r0.x, cb1[11].x
  iadd [precise(x)] r0.x, r1.x, r0.x
  iadd [precise(x)] r0.x, r0.x, cb1[14].x
  ishl [precise(x)] r0.x, r0.x, l(2)
  store_raw u0.x, r0.x, r0.y
endif 
ret 
// Approximately 19 instruction slots used


偏移401530h处第二段:
//
// Generated by Microsoft (R) HLSL Shader Compiler 10.1
//
//
// Buffer Definitions: 
//
// cbuffer CB_1
// {
//
//   uint _const_buffer_1[41];          // Offset:    0 Size:   644
//
// }
//
//
// Resource Bindings:
//
// Name                                 Type  Format         Dim      HLSL Bind  Count
// ------------------------------ ---------- ------- ----------- -------------- ------
// _GV_buffer_rw_0                       UAV    byte         r/w             u0      1 
// _GV_buffer_rw_1                       UAV    byte         r/w             u1      1 
// _GV_buffer_rw_2                       UAV    byte         r/w             u2      1 
// CB_1                              cbuffer      NA          NA            cb1      1 
//
//
//
// Input signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Input
//
// Output signature:
//
// Name                 Index   Mask Register SysValue  Format   Used
// -------------------- ----- ------ -------- -------- ------- ------
// no Output
cs_5_0
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB1[37], immediateIndexed
dcl_uav_raw u0
dcl_uav_raw u1
dcl_uav_raw u2
dcl_input vThreadID.xyz
dcl_temps 3
dcl_indexableTemp x0[3], 4
dcl_thread_group 32, 8, 1
imul [precise(x)] null, r0.x, vThreadID.z, cb1[0].x
imad [precise(x)] r0.x, vThreadID.y, cb1[1].x, r0.x
iadd [precise(x)] r0.x, r0.x, vThreadID.x
ult [precise(y)] r0.y, r0.x, cb1[2].x
if_nz r0.y
  udiv [precise(x)] r0.x, r1.x, r0.x, cb1[4].x                          //r0.x=n/3,r1.x=n%3
  mov [precise(x)] x0[0].x, l(-257992108802048.000000)                  //0xD76AA478
  mov [precise(x)] x0[1].x, l(-7545063049677084100000000.000000)        //0xE8C7B756
  mov [precise(x)] x0[2].x, l(0.000000)                                 //0x242070DB,这几个常数貌似有问题,用https://github.com/James-Jones/HLSLCrossCompiler里的工具反编译对比后修正一下
  iadd [precise(y)] r0.y, r1.x, cb1[11].x                               //r
  iadd [precise(y)] r0.y, r0.y, cb1[14].x                               //r0.y=r
  iadd [precise(z)] r0.z, r0.x, cb1[24].x                               //d
  iadd [precise(z)] r0.z, r0.z, cb1[27].x                               //r0.z=d
  mov [precise(w)] r0.w, l(0)                                           //
  mov [precise(y)] r1.y, l(32)                                          //
  mov [precise(zw)] r1.zw, r0.yyyz                                      //r1.z=r,r1.w=d
  mov [precise(x)] r2.x, l(-1)                                          //
  loop 
    breakc_z r2.x
    ishl [precise(yz)] r2.yz, r1.wwzw, l(0, 2, 2, 0)                    //r2.y=4d,r2.z=4r
    ld_raw_indexable [precise(y)](raw_buffer)(mixed,mixed,mixed,mixed) r2.y, r2.y, u1.xxxx      //r2.y=u1[d]
    ld_raw_indexable [precise(z)](raw_buffer)(mixed,mixed,mixed,mixed) r2.z, r2.z, u0.xxxx      //r2.z=u0[r]
    imad [precise(w)] r0.w, r2.y, r2.z, r0.w                            //r0.w+=u1[d] * u0[r]
    iadd [precise(w)] r1.w, r1.w, cb1[20].x                             //r1.w += 0x20
    iadd [precise(z)] r1.z, r1.z, cb1[7].x                              //r1.z += 3
    iadd [precise(y)] r1.y, r1.y, l(-1)                                 //r1.y--
    ult [precise(x)] r2.x, l(0), r1.y                                   //
  endloop 
  ishl [precise(y)] r0.y, l(1), r0.x                                    //r0.y=1<<d
  mov [precise(z)] r0.z, x0[r1.x + 0].x                                 //r0.z=k[r]
  and [precise(y)] r0.y, r0.y, r0.z                                     //r0.y &= k[r]
  bfi [precise(x)] r0.x, l(1), r0.x, r0.w, l(0)                         //
  xor [precise(x)] r0.x, r0.x, r0.y                                     //
  iadd [precise(y)] r0.y, r1.x, cb1[34].x                               //
  iadd [precise(y)] r0.y, r0.y, cb1[36].x                               //
  ishl [precise(y)] r0.y, r0.y, l(2)                                    //
  imm_atomic_xor [precise(x)] r0.x, u2, r0.y, r0.x                      //
endif 
ret 
// Approximately 39 instruction slots used



第一段HLSL就是把输入的12字节按位拆开,利用GPU的96个线程,每个处理一位,大概可以这样模拟:
void hlsl1(DWORD *t,BYTE *in)
{
        DWORD i;
        
        for (i=0;i<96;i++)
        {
                t[i] = (*(DWORD *)&in[(i%3)*4] >> i/3) & 1;;
        }
}


第二段HLSL也是利用GPU的96个线程,每个处理一位,实现的模2矩阵乘法,大概可以这样模拟:
void hlsl2(DWORD *t,DWORD *array,BYTE *out)
{
        DWORD d,r;
        DWORD m;
        DWORD i,j;
        DWORD b;
        DWORD k[3] = {0xD76AA478,0xE8C7B756,0x242070DB,0};

        for (i=0;i<96;i++)
        {
                m = 0;
                d = i / 3;
                r = i % 3;
                for (j=0;j<0x20;j++)
                {
                        m += t[r+j*4] * array[d+j*0x20];
                }
                b = k[r] & (1 << d);
                b ^= (m & 1) << d;
                *(DWORD *)&out[r*4] ^= b;
        }
}

正规解法应该可以求出逆矩阵,以前有个软件winiso的注册算法用的就是这种模2矩阵,因为3个DWORD可以单独处理,在穷举承受范围内,所以还是穷举半小时出结果。
最终结果:ThisIsAnEasyFlag


[招聘]欢迎市场人员加入看雪学院团队!

最后于 2018-7-7 12:18 被kanxue编辑 ,原因:
上传的附件:
最新回复 (8)
lelfei 21 2018-7-6 12:29
2
0
膜拜大神!穷举过程还能不能简化?(其实就是在问有没有超出穷举10分钟的限制)
kanxue 8 2018-7-6 14:55
3
0
膜拜大神!
wsc 2018-7-6 15:55
4
0
膜拜大神
点中你的心 2018-7-7 07:47
5
0
膜拜大佬
asasqq 2018-7-16 13:19
6
0
膜拜大佬
AloneWolf 3 2018-7-16 13:57
7
0
膜拜大神!!!
福否阿卡 2018-7-28 18:08
8
0
大神喝茶
喜欢二二 2018-8-10 10:40
9
0
膜拜大佬
游客
登录 | 注册 方可回帖
返回