首页
论坛
课程
招聘
[原创] KCTF 2021 Win. 第二题 排排坐
2021-11-17 23:23 13885

[原创] KCTF 2021 Win. 第二题 排排坐

HHHso 活跃值
22
2021-11-17 23:23
13885

排排坐

【摘要】

    正向检验算法还算直观,其唯一解的数学原理未知,但不妨碍我们直接爆破。


第1节 正向算法

1.1 着力点

    我们直接关注图1-1中代码,通过GetDlgItemTextA交叉索引得到。

    通过基本分析,我们得到:

(1)Hi_this_obuf_icode_len__hex2bytes 将输入的32字节长lv_code通过16进制转换胃16字节,应该注意lv_code与转换后的Hi_codeLH的差异性,如

input code hex:= "0123456789ABCDEF" +  "0123456789ABCDEF"
经过转换
inner code bin:=  1032547698BADCFE  ::  1032547698BADCFE
unsigned char inner_code_bin[0x10] = {0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, ...}
即'01'转换为0x10,'23'转换为0x32,以此类推。

(2)转换后的16字节Hi_codeLH ,我们分为codeL,codeH高低(各8字节)两部分,其中抵8字节codeL填充了codeLSalt数组;

(3)Hi_last_check函数是核心检验函数。


图1-1 着手代码片段

1.2 核心校验框架

    如Hi_last_check的伪码和图1-2,代码框架分割为四部分。

(1)第一部分,检测codeLSalt的有效性,codeLSalt大小为0x100字节,如上所述,前8字节来自输入的codeL。

(2)第二部分,对codeLSalt进行变换;

(3)第三部分,利用codeLSalt和codeH对bsuk进行变换,bsuk初始值为codeLsalt前8字节;

(4)第四部分,变换后的bsuk是否为“GoodJob~”。


图1-2 Hi_last_check主要业务逻辑

int __thiscall Hi_last_check(HWND *this, char *codeH)
{
  int lv_i; // ebp
  char *v3; // eax
  int *v4; // esi
  char *btsx; // ecx
  int v6; // edi
  _BYTE *v7; // ecx
  int v8; // edx
  char *v9; // eax
  int v10; // ecx
  int v11; // esi
  int v12; // eax
  unsigned __int8 v13; // dl
  int v14; // edi
  int v15; // eax
  int v16; // ecx
  int chi; // esi
  int i; // eax
  char v19; // dl
  char lv_a; // [esp+10h] [ebp-Ch]
  char lv_b; // [esp+11h] [ebp-Bh]
  char lv_c; // [esp+12h] [ebp-Ah]
  unsigned __int8 lv_d; // [esp+13h] [ebp-9h]
  char (*lv_gbsptr)[256]; // [esp+14h] [ebp-8h]

  //-----------------第一部分开始
  lv_a = 0;
  lv_b = 0;
  lv_c = 0;
  lv_d = 0;
  lv_i = 1;
  lv_gbsptr = Hi_gbsA;
  do
  {
    Hi_bts[0] = codeLSalt[lv_i - 1];
    Hi_bts[1] = lv_i;
    v3 = Hi_bts;
    v4 = &Hi_cns;
    btsx = &Hi_bts[Hi_cns];
    do
    {
      v6 = *v4;
      if ( *v4 > 0 )
      {
        do
        {
          v7 = btsx + 1;
          *(v7 - 1) = codeLSalt[(unsigned __int8)*v3];
          *v7 = *v3 + 1;
          btsx = v7 + 1;
          ++v3;
          --v6;
        }
        while ( v6 );
      }
      ++v4;
    }
    while ( (int)v4 < (int)&Hi_cns_end );
    v8 = 256;
    do
    {
      ++(*lv_gbsptr)[(unsigned __int8)*v3++];
      --v8;
    }
    while ( v8 );
    ++lv_i;
    ++lv_gbsptr;
  }
  while ( lv_i - 1 < 256 );
  v9 = &Hi_gbsA[0][40];
  v10 = 256;
  do
  {
    if ( *(v9 - 40) )
      ++lv_a;
    if ( *(v9 - 26) )
      ++lv_b;
    if ( *v9 )
      ++lv_c;
    if ( v9[39] )
      ++lv_d;
    v9 += 256;
    --v10;
  }
  while ( v10 );
  if ( lv_a == (char)0xA9 && lv_b == (char)0xAC && lv_c == (char)0xA7 && lv_d > 0xC8u )
  {
    //-------------------------第二部分开始
    v11 = 0;
    while ( 2 )
    {
      v12 = 0;
      while ( (unsigned __int8)codeLSalt[v12] != v11 )
      {
        if ( ++v12 >= 256 )
          goto LABEL_32;
      }
      v13 = codeLSalt[v11];
      v14 = 0;
      v15 = v11;
      if ( v11 != v13 )
      {
        do
        {
          ++v14;
          v16 = (unsigned __int8)codeLSalt[v15];
          codeLSalt[v15] = codeLSalt[v16];
          v15 = v16;
          if ( v14 >= 256 )
            return 0;
        }
        while ( v11 != (unsigned __int8)codeLSalt[v16] );
      }
      codeLSalt[v15] = v13;
LABEL_32:
      if ( ++v11 < 256 )
        continue;
      break;
    }
    //------------------------------第三部分开始
    chi = 0;
    *(_QWORD *)&bsuk = *(_QWORD *)codeLSalt;
    do
    {
      for ( i = 0; i < 8; ++i )
      {
        if ( chi >= 8 )
        {
          if ( !i || i == 7 )
            --*(&bsuk + i);
        }
        else
        {
          if ( (codeH[i] & 1) != 0 )
            v19 = *(&bsuk + i) + 1;
          else
            v19 = codeLSalt[(unsigned __int8)*(&bsuk + i)];
          *(&bsuk + i) = v19;
          codeH[i] = (unsigned __int8)codeH[i] >> 1;
        }
      }
      ++chi;
    }
    while ( chi < 9 );
    //-------------------------------第四部分开始,作最后检测校对
    if ( !Hi_strncmp(&bsuk, bsC, 8) )
    {
      MessageBoxA(this[1], bsC, Caption, 0x40u);
      return 1;
    }
  }
  return 0;
}

第2节 直接爆破

    针对核心算法操作的四个部分(忽略最后的strncmp,实际是三部分)进行爆破。

2.1 有效的codeLSalt

    如图1-3,对codeLSalt的有效性检测,实际也分为四各小步骤,基本算法描述为:

(1)定义全局变量
unsigned char codeLSalt[0x100] = {...};
unsigned char bts[0x200] = {0}; //细分各小段长度依次为 0x02+0x04+0x08+0x10+0x20+0x40+0x80+0x100+0x02 
int cns[8]={0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00} //
unsigned char gbsA[0x100][0x100] = {...};

(2)演化
对于每个codeLSalt[i],其中i=0,1,...0xFF
bts[0]=codeLSalt[i],bts[1]=i+1; 即初始化bts最开始的两字节片段,
然后利用codeLSalt和cns,逐段衍生后续片段,直到完成bts中最后0x100大小片段的衍生

(3)统计
对于每个i对应codeLSaolt[i]衍生的最后0x100大小片段中出现的数字,进行个数统计,记录仔gbsA[i]中,


(3.1)举例说明

假如codeSalt[0x100]={
  0x4B,0x6D,0x28,0x8C,0xFB,0xD2,0x1E,0xA3,0xA2,0x9B,0xF4,0xDF,0xAC,0x7C,0xA1,0xC6,
  0x16,0xD0,0x0F,0xDD,0xDC,0x73,0xC5,0x6B,0xD1,0x96,0x47,0xC2,0x26,0x67,0x4E,0x41,
  0x82,0x20,0x56,0x9A,0x6E,0x33,0x92,0x88,0x29,0xB5,0xB4,0x71,0xA9,0xCE,0xC3,0x34,
  0x50,0x59,0xBF,0x2D,0x57,0x22,0xA6,0x30,0x04,0xB2,0xCD,0x36,0xD5,0x68,0x4D,0x5B,
  0x45,0x9E,0x85,0xCF,0x9D,0xCC,0x61,0x78,0x32,0x76,0x31,0xE3,0x80,0xAD,0x39,0x4F,
  0xFA,0x72,0x83,0x4C,0x86,0x60,0xB7,0xD7,0x63,0x0C,0x44,0x35,0xB3,0x7B,0x19,0xD4,
  0x69,0x08,0x0B,0x1F,0x3D,0x11,0x79,0xD3,0xEE,0x93,0x42,0xDE,0x23,0x3B,0x5D,0x8D,
  0xA5,0x77,0x5F,0x58,0xDB,0x97,0xF6,0x7A,0x18,0x52,0x15,0x74,0x25,0x62,0x2C,0x05,
  0xE8,0x0D,0x98,0x2A,0x43,0xE2,0xEF,0x48,0x87,0x49,0x1C,0xCA,0x2B,0xA7,0x8A,0x09,
  0x81,0xE7,0x53,0xAA,0xFF,0x6F,0x8E,0x91,0xF1,0xF0,0xA4,0x46,0x3A,0x7D,0x54,0xEB,
  0x2F,0xC1,0xC0,0x0E,0xBD,0xE1,0x6C,0x64,0xBE,0xE4,0x02,0x3C,0x5A,0xA8,0x9F,0x37,
  0xAF,0xA0,0x13,0xED,0x1B,0xEC,0x8B,0x3E,0x7E,0x27,0x99,0x75,0xAB,0xFE,0xD9,0x3F,
  0xF3,0xEA,0x70,0xF7,0x95,0xBA,0x1D,0x40,0xB0,0xF9,0xE5,0xF8,0x06,0xBC,0xB6,0x03,
  0xC9,0x10,0x9C,0x2E,0x89,0x5C,0x7F,0xB1,0x1A,0xD6,0x90,0xAE,0xDA,0xE6,0x5E,0xB9,
  0x84,0xE9,0x55,0xBB,0xC7,0x0A,0xE0,0x66,0xF2,0xD8,0xCB,0x00,0x12,0xB8,0x17,0x94,
  0x6A,0x4A,0x01,0x24,0x14,0x51,0x07,0x65,0x21,0xC8,0x38,0xFD,0x8F,0xC4,0xF5,0xFC,
};



对于i=0,则有bts[0x200] = {
4B 01 
      E3 4C 6D 02 
                  BB E4 80 4D 3B 6E 28 03 
                                          75 BC
C7 E5 E8 81 AD 4E 36 3C 5D 6F 29 29 8C 04 
                                          97 76
AB BD 40 C8 0A E6 F2 E9 0D 82 A8 AE 39 4F A6 37
D5 3D 7B 5E 8D 70 B5 2A B5 2A 2B 8D FB 05 
                                          91 98
F6 77 3C AC FE BE 45 41 B0 C9 F4 0B E0 E7 01 F3
D8 EA 7C 0E 98 83 BE A9 9F AF B2 3A 4F 50 6C A7
30 38 5C D6 68 3E 74 7C 19 5F A7 8E A5 71 EC B6
B4 2B EC B6 B4 2B 71 2C A7 8E FD FC D2 06 
                                          E7 92
F1 99 07 F7 7A 78 D5 3D 5A AD F5 FF D9 BF CC 46
9E 42 AF B1 F9 CA 14 F5 DF 0C 84 E1 66 E8 6D 02
24 F4 1A D9 CB EB 25 7D A1 0F F1 99 2A 84 D9 BF
E4 AA EB A0 37 B0 13 B3 CD 3B 4F 50 FA 51 23 6D
64 A8 50 31 04 39 B3 5D 7F D7 EE 69 4D 3F DB 75
25 7D 96 1A D4 60 64 A8 8A 8F E1 A6 77 72 12 ED
8B B7 1B B5 71 2C 12 ED 8B B7 1B B5 71 2C 77 72
A9 2D 64 A8 8A 8F C4 FE 8F FD 9C D3 1E 07 
                                          66 E8
53 93 4A F2 F0 9A A3 08 65 F8 15 7B 18 79 5C D6
68 3E 44 5B A8 AE 51 F6 FC 00 D6 DA 3F C0 06 CD
61 47 54 9F 85 43 37 B0 A0 B2 C8 FA E5 CB DC 15
51 F6 B9 E0 AC 0D 43 85 E9 E2 79 67 F2 E9 3B 6E
28 03 6E 25 14 F5 47 1B D6 DA F8 CC 00 EC 33 26
62 7E C1 A2 C6 10 4A F2 F0 9A B4 2B 43 85 D6 DA
3F C0 C7 E5 02 AB 00 EC 2F A1 30 38 AF B1 DD 14
ED B4 BC CE 36 3C 4F 50 FA 51 38 FB 72 52 9A 24
3B 6E 3D 65 BE A9 FA 51 59 32 FB 05 B2 3A ED B4
7B 5E 05 80 B1 D8 17 EF 93 6A AD 4E 5B 40 AE DC
97 76 33 26 62 7E 8E 97 47 1B 89 D5 69 61 3D 65
BE A9 1C 8B 09 90 E9 E2 6C A7 7A 78 5F 73 0F 13
B8 EE CA 8C 3E B8 C2 1C EC B6 77 72 A9 2D 0F 13
B8 EE CA 8C 3E B8 C2 1C EC B6 77 72 A9 2D 7A 78
5F 73 E4 AA CE 2E 3D 65 BE A9 1C 8B 09 90 95 C5
F5 FF 09 90 C4 FE 3A 9D 2E D4 4E 1F A3 08 
                                          00 00
}

因为,对于i=0,
bts[0x200]第1片段为0x02字节长,为codeLSalt[i],i+1,则对应 4B 01;
然后利用codeLSalt和cns[0] = 2,得到codeLSalt[0x4B],0x4B+1,codeLSalt[0x01],0x01+1,则对应 E3 4C 6D 02;
同理,利用codeLSalt和cns[1] = 0x04,得到BB E4 80 4D 3B 6E 28 03 ;
以此类推,直到得到最后0x100长的片段。

由最后0x100长片段,我们得到gbsA[i];
其中 gbsA[i][0] = 0x03,表示统计最后0x100长片段中0x00出现了3次,
同理,通过统计,0x01没有出现,所以gbsA[i][1]==0x00,以此类推

gbsA[i][] = {
03 00 01 01 00 02 01 00 02 03 00 00 00 01 00 02
01 00 00 02 02 02 00 01 01 00 00 02 04 00 00 01
00 00 00 00 01 01 02 00 01 00 00 01 00 02 02 01
01 00 01 02 00 00 01 01 02 00 02 02 01 03 03 02
01 00 00 03 01 00 00 03 00 00 02 00 00 00 02 01
01 04 01 01 01 00 00 00 00 01 00 02 01 00 01 02
00 02 02 00 00 04 01 01 01 01 01 00 01 00 03 00
00 00 03 02 00 00 01 02 02 02 02 02 00 00 02 00
01 00 00 00 00 03 00 00 00 01 00 02 02 00 01 00
03 00 00 02 00 01 00 02 00 00 03 00 00 01 00 01
01 01 01 02 00 00 00 01 01 05 01 01 01 01 02 01
01 02 02 00 03 00 02 00 04 01 00 00 01 00 03 00
02 01 02 00 01 01 01 01 01 00 02 01 01 01 02 00
00 00 00 00 01 01 04 00 01 00 03 00 02 01 00 00
01 00 02 00 01 02 00 00 01 03 00 00 04 02 02 01
02 00 03 00 00 02 02 00 02 00 03 02 01 00 01 01
}

(4)针对性统计,校对
针对通过所有的gbsA[i][],其中i=0,1,..0xFF
统计所有衍生的最后0x100长度片段中,0, 14, 40, 79分别出现的总此书,依次记录为a,b,c,d
要求a == 0xA9 && b == 0xAC && c == 0xA7 && d > 0xC8,如果满足,则codeLSalt有效

图1-3 codeLSalt有效性

2.2 枚举爆破得到有效codeLSalt

    如图1-4,我们直到codeLSalt的大小为0x100,且初始末端的0x100-8字节都已经固定,通过观察,我们可以判定,其为0x00-0xFF的非重复排列,作为基准映射表使用。

    由此出发,我们可以确定codeLSalt前8字节的取值集合,执行下述idapython

cst = set(ida_bytes.get_bytes(0x404000+8,0x100-8)) #cs mapping's tail bytes' set
csa = set([i for i in range(0x100)])               #cs mapping's all  bytes' set
csl = list(csa - cst)                                    #cs mapping's first head 8-bytes' set

#Out:==> [30, 40, 75, 109, 140, 163, 210, 251]

即codeL为[30, 40, 75, 109, 140, 163, 210, 251]的排列,有多少排列?

from itertools import permutations
pl = [p for p in permutations(csl, 8)]
len(pl)
#Out==》 40320  #we have 40320 permutations for csl (or inner_code_bin[0,1,...7])

即codeL有40320种情形,我们以此为爆破入口,遍历所有情形,找到有效排列,通过下述pythn代码,我们将所有可能排列,顺序存放到pbs.bin文件中备用。

#here we try to save all 40320 cases of {cs[i]===inner_code_bin[i] | i = 0,1,...,7} to pbs.bin file
#
with open(r'D:\CTF2021\KCTFP\KCTF02\pbs.bin','wb') as fout:
  fout.write(b''.join([bytes(list(p)) for p in pl]))


图1-4 codeLSalt初始值

(1)编译执行附件find_codeLSalt.c代码,如下
cl find_codeLSalt.c cutils.c
ind_codeLSalt.exe 0 40230 .\pbs.bin

(2)我们得到
find_codeLSalt.exe 0 40230 .\pbs.bin
[Start Time]: 2021/11/17 22:38:10
Read pbs from .\pbs.bin ok.
Check from 0 to 40230 start:
=======> Found i := 12399       at 2021/11/17 22:38:35
        pbs[i][] = {0x4B,0x6D,0x28,0x8C,0xFB,0xD2,0x1E,0xA3};
Check from 0 to 40230 end!
[End   Time]: 2021/11/17 22:39:31

(3)即我们仔40230种排列中,找到唯一的有效codeL为 0x4B,0x6D,0x28,0x8C,0xFB,0xD2,0x1E,0xA3,这位codeLSalt的前8字节,
其余字节参考图1-4内容。


于是我们由codeL得到code的前16字节输入为 "B4D682C8BF2DE13A"

2.3 codeLSalt的变换xcs

(1)编译执行附件
cl gen_xcs.c cutils.c
gen_xcs.exe 12399 .\pbs.bin

(2)我们得到第二部分codeLSalt的变换xcs
gen_xcs.exe 12399 .\pbs.bin
[Start Time]: 2021/11/17 22:48:42
Read pbs from .\pbs.bin ok.
The cs is:
  0x4B,0x6D,0x28,0x8C,0xFB,0xD2,0x1E,0xA3,0xA2,0x9B,0xF4,0xDF,0xAC,0x7C,0xA1,0xC6,
  0x16,0xD0,0x0F,0xDD,0xDC,0x73,0xC5,0x6B,0xD1,0x96,0x47,0xC2,0x26,0x67,0x4E,0x41,
  0x82,0x20,0x56,0x9A,0x6E,0x33,0x92,0x88,0x29,0xB5,0xB4,0x71,0xA9,0xCE,0xC3,0x34,
  0x50,0x59,0xBF,0x2D,0x57,0x22,0xA6,0x30,0x04,0xB2,0xCD,0x36,0xD5,0x68,0x4D,0x5B,
  0x45,0x9E,0x85,0xCF,0x9D,0xCC,0x61,0x78,0x32,0x76,0x31,0xE3,0x80,0xAD,0x39,0x4F,
  0xFA,0x72,0x83,0x4C,0x86,0x60,0xB7,0xD7,0x63,0x0C,0x44,0x35,0xB3,0x7B,0x19,0xD4,
  0x69,0x08,0x0B,0x1F,0x3D,0x11,0x79,0xD3,0xEE,0x93,0x42,0xDE,0x23,0x3B,0x5D,0x8D,
  0xA5,0x77,0x5F,0x58,0xDB,0x97,0xF6,0x7A,0x18,0x52,0x15,0x74,0x25,0x62,0x2C,0x05,
  0xE8,0x0D,0x98,0x2A,0x43,0xE2,0xEF,0x48,0x87,0x49,0x1C,0xCA,0x2B,0xA7,0x8A,0x09,
  0x81,0xE7,0x53,0xAA,0xFF,0x6F,0x8E,0x91,0xF1,0xF0,0xA4,0x46,0x3A,0x7D,0x54,0xEB,
  0x2F,0xC1,0xC0,0x0E,0xBD,0xE1,0x6C,0x64,0xBE,0xE4,0x02,0x3C,0x5A,0xA8,0x9F,0x37,
  0xAF,0xA0,0x13,0xED,0x1B,0xEC,0x8B,0x3E,0x7E,0x27,0x99,0x75,0xAB,0xFE,0xD9,0x3F,
  0xF3,0xEA,0x70,0xF7,0x95,0xBA,0x1D,0x40,0xB0,0xF9,0xE5,0xF8,0x06,0xBC,0xB6,0x03,
  0xC9,0x10,0x9C,0x2E,0x89,0x5C,0x7F,0xB1,0x1A,0xD6,0x90,0xAE,0xDA,0xE6,0x5E,0xB9,
  0x84,0xE9,0x55,0xBB,0xC7,0x0A,0xE0,0x66,0xF2,0xD8,0xCB,0x00,0x12,0xB8,0x17,0x94,
  0x6A,0x4A,0x01,0x24,0x14,0x51,0x07,0x65,0x21,0xC8,0x38,0xFD,0x8F,0xC4,0xF5,0xFC,
The xcs is:
  0xC1,0x9B,0x7F,0x58,0x64,0xD5,0x77,0x21,0x74,0xEB,0x14,0xBF,0xDF,0x25,0x5A,0x37,
  0x85,0x2C,0xAF,0x8C,0xDA,0x26,0xE2,0x7A,0x87,0x4C,0x60,0x99,0x54,0x3C,0x95,0xC0,
  0xB9,0x0C,0xBC,0x0E,0xE7,0x2D,0x86,0xBE,0x67,0xD3,0xD8,0xFC,0x30,0xB6,0xC8,0x57,
  0x1E,0x62,0x3E,0xCE,0xA0,0xCD,0xF5,0xEE,0xA7,0xCF,0x45,0xFE,0xD0,0x80,0x05,0xAD,
  0x13,0xF3,0xB7,0x6B,0x22,0x2B,0xBD,0x69,0x42,0x4B,0xA5,0xEA,0xA6,0xD2,0x6F,0x4F,
  0x4E,0x07,0xE1,0x36,0x01,0xB5,0xAA,0xB1,0x94,0x0B,0x35,0x3A,0xC7,0x49,0x53,0x82,
  0xC3,0x7B,0x32,0xFF,0x19,0xC4,0xF1,0xC9,0xE8,0xF7,0x56,0x15,0xA3,0x46,0x89,0x43,
  0x9D,0x8F,0x20,0xEF,0xBB,0x2A,0xCB,0x09,0x93,0x4A,0x1C,0xE3,0x33,0xD1,0xE0,0x1D,
  0x72,0x7C,0x27,0xE9,0x17,0x28,0x6D,0x6A,0xD9,0x00,0x9A,0xE5,0x63,0xDE,0x23,0x9F,
  0x0D,0x47,0x3B,0x65,0x08,0x84,0x6C,0x1A,0x88,0x12,0xA1,0xA4,0xB3,0x18,0x24,0x1B,
  0xD7,0x44,0xDB,0xAC,0x6E,0x7D,0x51,0x5E,0xED,0x50,0xD6,0x11,0x5B,0x9C,0xB4,0x68,
  0x3D,0x2F,0x03,0x40,0xBA,0x2E,0xCA,0x02,0xE6,0xA8,0xEC,0x83,0x06,0x5D,0xB8,0x4D,
  0x97,0x66,0xF0,0xFB,0x8A,0x55,0xAB,0xB2,0x04,0xFA,0x0A,0x31,0x71,0xCC,0x8B,0x73,
  0xA9,0x48,0x5C,0xF9,0x98,0xE4,0xC6,0x34,0xC5,0x7E,0x81,0x75,0x90,0x1F,0x92,0x3F,
  0x9E,0x10,0x29,0x52,0x39,0xF4,0x41,0x78,0x5F,0x16,0x79,0xC2,0xB0,0xDD,0xF2,0x61,
  0x0F,0x70,0xD4,0x91,0xDC,0xF6,0xF8,0xFD,0x59,0x38,0x8D,0x96,0xAE,0x8E,0x76,0xA2,
[End   Time]: 2021/11/17 22:48:42

2.3 codeH的爆破

    第三部分如图1-5,bsuk初始值为xcs的前8字节,即0xC1,0x9B,0x7F,0x58,0x64,0xD5,0x77,0x21;其经过9次变换,得到最终的bsuk;

每次通过codeLSalt的变换受codeH的影响;仔细分析我们可以发现,实际上bsuk各个字节的变换时独立的,受codeH对应单字节的影响;

于是我们可以枚举codeH[i]的值,从0x00到0xFF,对bsuk进行变换,如果得到最终“GoodJob~"对应字节,则表示找到了对应的codeH[i]

图1-5 bsuk的变换

(1)编译执行附件 find_codeH.c代码
cl find_codeH.c cutils.c
find_codeH.exe GoodJob~
cH[0]:
        0x9D
cH[1]:
        0x6B
cH[2]:
        0xEA
cH[3]:
        0x2F
cH[4]:
        0xA4
cH[5]:
        0x08
cH[6]:
        0xBC
cH[7]:
        0x22
        
(2) 于是我们得到codeH  = [0x9D,0x6B,0xEA,0x2F,0xA4,0x08,0xBC,0x22]
即codeH的输入部分为D9B6AEF24A80CB22

结合codeL对应输入为"B4D682C8BF2DE13A",和codeH对应输入为D9B6AEF24A80CB22,

我们得到code = "B4D682C8BF2DE13AD9B6AEF24A80CB22"


第3节 总结

    爆破代码,主要直接模仿业务逻辑的汇编代码,以免C伪码或python伪码产生误差,实际也依然会一个小心存在缺漏而导致错误出现,相对而言,直接模仿汇编查漏补缺和灵活复用上比较中庸。也尝试了利用idapython的ida_dbg和ida_idd进行自动化重复条用,但事件和指针回滚间隔响应时间有缺陷而停止,其他就是以python或api方式干预样本进程运行,又或者以shellcode方式,甚至unicorn模式方式运行重复利用核心代码,这些都可以作为尝试思路。



附件为所产生的数据和使用代码,编译一般直接仔命令行通过cl.exe编译。



【公告】欢迎大家踊跃尝试高研班11月试题,挑战自己的极限!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (1)
雪    币: 4121
活跃值: 活跃值 (1953)
能力值: ( LV6,RANK:81 )
在线值:
发帖
回帖
粉丝
KingSelyF 活跃值 1 2021-11-18 18:33
2
0
膜拜大佬
游客
登录 | 注册 方可回帖
返回