首页
论坛
课程
招聘
[原创]看雪.TSRC 2017CTF秋季赛第五题writeup
2017-11-2 12:46 1758

[原创]看雪.TSRC 2017CTF秋季赛第五题writeup

2017-11-2 12:46
1758

begin

本人水平比较菜,做题只能靠玄学。做出来的时候也感觉有点点小不可思议。因为并没有对所有的流程都分析的很清楚。

反调试判断

 

在这一个位置有一个 int 2d 中断来验证

 

上网查了一下 int 2d的特性 是无调试的时候异常,有调试的时候正常运行。所以之后这个位置的

 

 

Vm0wd2QyUXlVWGw== 就是不会比对的,会直接跳到except处,因此程序会跳到40717d开始执行

 

算法部分

.text:00407010                 mov     esi, offset aKanxuecrackme2 ; "KanXueCrackMe2017"
.text:00407015                 lea     edi, [ebp+kanxue]
.text:00407018                 movsd
.text:00407019                 movsd
.text:0040701A                 movsd
.text:0040701B                 movsd
.text:0040701C                 movsw
.text:0040701E                 xor     eax, eax
.text:00407020                 lea     edi, [ebp+var_3A]
.text:00407023                 stosw
.text:00407025                 lea     eax, [ebp+kanxue]
.text:00407028                 push    eax
.text:00407029                 lea     eax, [ebp+var_D9F4]
.text:0040702F                 push    eax
.text:00407030                 call    sub_4084A3  // 让KanXueCrackMe2017字符串在sub_4084A3这个函数进行加密
//-------------------------------------------------------------------------------
.text:0040717D                 mov     esp, [ebp+ms_exc.old_esp] ; Exception handler 0 for function 406FC3
.text:00407180                 lea     eax, [ebp+var_38]
.text:00407183                 push    eax
.text:00407184                 lea     eax, [ebp+var_D9F4]
.text:0040718A                 push    eax
.text:0040718B                 call    sub_4084A3  // 让输入的字符串在sub_4084A3这个函数进行加密

关键就是在于 sub_4084A3 这个函数的分析,直接上伪代码把

void __stdcall sub_4084A3(int a1, const char *a2)
{
  signed int i; // ebx@1
  signed int v3; // edi@2
  char v4; // al@3
  const char *v5; // [sp+0h] [bp-4h]@1
  signed int v6; // [sp+10h] [bp+Ch]@1

  v5 = (const char *)malloc(3 * strlen(a2));
  sub_40829C(a2, (int)v5);                      //将KanXueCrackMe2017字符串以及输入的字符串做一定的处理,加密后的值为 0-9A-H 这个范围
  v6 = strlen(v5);
  i = 0;
  if ( v6 > 0 )                             
  {
    v3 = v6;
    do
    {
      v4 = v5[i];
      if ( v4 < '0' || v4 > '9' )
      {
        if ( v4 >= 'A' && v4 <= 'H' )
          v3 = v4 - 55;
      }
      else
      {
        v3 = v4 - 0x30;
      }
      sub_4080DF(v3 / 3, v3 % 3 + 1, a1);    //基于 0-9A-H 转化为 0-17 然后对一个数组进行处理。
      ++i;
    }
    while ( i < v6 );
  }
  free((void *)v5);
}

sub_4080DF位置 核心的操作就是 对 一个刚开始为 0至0x2f递增排列的数组按位置进行一个处理。

 

第一次是通过 KanXueCrackMe2017字符串 加密后的值 对0至0x2f递增排列的数组 按照一定规则进行打乱。

 

而 加密后的输入字符串 需要对这个数组进行还原回 0至0x2f递增排列的数组。

 

然后就所有人应该都卡在这里了,包括我。

 

对于sub_40829C的分析

 

在其中某个子函数中有中文,除法算法出错、模错误。。。等等中文,,推测可能是网上扒来的代码,应该不是自己写的一个很复杂加密。
尝试上网查过这个算法,但是失败了。

 

这一段最后是靠前后数据推理出来的。

 

刚开始测试输入的数据很大,然后没有思路,后来测试了一下小数

01 83
11 93
21 A3
31 B3
41 C3
51 D3
61 E3
71 F3
81 G3
91 H3
A1 04
02 G6
12 H6
13 7A

推理了一下就发现这个其实就是一个 18进制转为62进制的数

 

至于62进制,,由于输入的值是在0-9a-zA-Z 10+26+26=62 然后就是62进制,

 

使用python实现了一下还原脚本

ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

def base62_encode(num, alphabet=ALPHABET):
    if (num == 0):
        return alphabet[0]
    arr = []
    base = len(alphabet)
    while num:
        rem = num % base
        num = num // base
        arr.append(alphabet[rem])
    arr.reverse()
    return ''.join(arr)

a = int("46F9C1H147E25CFAE"[::-1],18)
print base62_encode(a)[::-1]

然后后面的就是 sub_4080DF

 

可以发现v4 = v5[i];

 

这个v4的范围是在A-H(0-17)

 

因为这个变换就是表的变换,而且只有18次 然后不嫌麻烦的我直接手动扣了一下数组。

map = [[0x06,0x07,0x00,0x01,0x02,0x03,0x04,0x05,0x08,0x09,0x0A,0x0B,0x22,0x23,0x24,0x0F,0x0E,0x11,0x12,0x13,0x14,0x15,0x0C,0x0D,0x16,0x17,0x10,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x18,0x19,0x1A,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x04,0x05,0x06,0x07,0x00,0x01,0x02,0x03,0x08,0x09,0x0A,0x0B,0x18,0x19,0x1A,0x0F,0x24,0x11,0x12,0x13,0x14,0x15,0x22,0x23,0x0C,0x0D,0x0E,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x16,0x17,0x10,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x02,0x03,0x04,0x05,0x06,0x07,0x00,0x01,0x08,0x09,0x0A,0x0B,0x16,0x17,0x10,0x0F,0x1A,0x11,0x12,0x13,0x14,0x15,0x18,0x19,0x22,0x23,0x24,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x0C,0x0D,0x0E,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x10,0x11,0x12,0x03,0x04,0x05,0x06,0x07,0x0E,0x0F,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x2C,0x2D,0x2E,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x00,0x01,0x02,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x20,0x21,0x22,0x2F],
[0x2C,0x2D,0x2E,0x03,0x04,0x05,0x06,0x07,0x0C,0x0D,0x0E,0x0F,0x08,0x09,0x0A,0x0B,0x20,0x21,0x22,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x10,0x11,0x12,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x00,0x01,0x02,0x2F],
[0x20,0x21,0x22,0x03,0x04,0x05,0x06,0x07,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x08,0x09,0x00,0x01,0x02,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x2C,0x2D,0x2E,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x10,0x11,0x12,0x2F],
[0x00,0x01,0x1A,0x1B,0x1C,0x05,0x06,0x07,0x08,0x09,0x02,0x03,0x04,0x0D,0x0E,0x0F,0x16,0x17,0x10,0x11,0x12,0x13,0x14,0x15,0x18,0x19,0x2A,0x2B,0x2C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x0A,0x0B,0x0C,0x2D,0x2E,0x2F],
[0x00,0x01,0x2A,0x2B,0x2C,0x05,0x06,0x07,0x08,0x09,0x1A,0x1B,0x1C,0x0D,0x0E,0x0F,0x14,0x15,0x16,0x17,0x10,0x11,0x12,0x13,0x18,0x19,0x0A,0x0B,0x0C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x02,0x03,0x04,0x2D,0x2E,0x2F],
[0x00,0x01,0x0A,0x0B,0x0C,0x05,0x06,0x07,0x08,0x09,0x2A,0x2B,0x2C,0x0D,0x0E,0x0F,0x12,0x13,0x14,0x15,0x16,0x17,0x10,0x11,0x18,0x19,0x02,0x03,0x04,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x1A,0x1B,0x1C,0x2D,0x2E,0x2F],
[0x00,0x01,0x02,0x03,0x24,0x25,0x26,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x04,0x05,0x06,0x17,0x1E,0x1F,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x20,0x21,0x22,0x23,0x28,0x29,0x2A,0x27,0x14,0x15,0x16,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x00,0x01,0x02,0x03,0x28,0x29,0x2A,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x24,0x25,0x26,0x17,0x1C,0x1D,0x1E,0x1F,0x18,0x19,0x1A,0x1B,0x20,0x21,0x22,0x23,0x14,0x15,0x16,0x27,0x04,0x05,0x06,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x00,0x01,0x02,0x03,0x14,0x15,0x16,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x28,0x29,0x2A,0x17,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x18,0x19,0x20,0x21,0x22,0x23,0x04,0x05,0x06,0x27,0x24,0x25,0x26,0x2B,0x2C,0x2D,0x2E,0x2F],
[0x08,0x01,0x02,0x03,0x04,0x05,0x0E,0x0F,0x28,0x09,0x0A,0x0B,0x0C,0x0D,0x2E,0x2F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x00,0x19,0x1A,0x1B,0x1C,0x1D,0x06,0x07,0x26,0x27,0x20,0x21,0x22,0x23,0x24,0x25,0x18,0x29,0x2A,0x2B,0x2C,0x2D,0x1E,0x1F],
[0x28,0x01,0x02,0x03,0x04,0x05,0x2E,0x2F,0x18,0x09,0x0A,0x0B,0x0C,0x0D,0x1E,0x1F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x08,0x19,0x1A,0x1B,0x1C,0x1D,0x0E,0x0F,0x24,0x25,0x26,0x27,0x20,0x21,0x22,0x23,0x00,0x29,0x2A,0x2B,0x2C,0x2D,0x06,0x07],
[0x18,0x01,0x02,0x03,0x04,0x05,0x1E,0x1F,0x00,0x09,0x0A,0x0B,0x0C,0x0D,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x28,0x19,0x1A,0x1B,0x1C,0x1D,0x2E,0x2F,0x22,0x23,0x24,0x25,0x26,0x27,0x20,0x21,0x08,0x29,0x2A,0x2B,0x2C,0x2D,0x0E,0x0F],
[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x12,0x13,0x14,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x1C,0x1D,0x1E,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x26,0x27,0x20,0x1F,0x0A,0x21,0x22,0x23,0x24,0x25,0x08,0x09,0x2E,0x2F,0x28,0x29,0x2A,0x2B,0x2C,0x2D],
[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x1C,0x1D,0x1E,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x26,0x27,0x20,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x08,0x09,0x0A,0x1F,0x14,0x21,0x22,0x23,0x24,0x25,0x12,0x13,0x2C,0x2D,0x2E,0x2F,0x28,0x29,0x2A,0x2B],
[0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x26,0x27,0x20,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x08,0x09,0x0A,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x12,0x13,0x14,0x1F,0x1E,0x21,0x22,0x23,0x24,0x25,0x1C,0x1D,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x28,0x29]]

后面有一个地方是

.text:004071AB                 push    eax
.text:004071AC                 call    sub_40680C
.text:004071B1                 cmp     eax, 1
.text:004071B4                 jnz     short loc_4071D9
.text:004071B6                 lea     eax, [ebp+var_38]
.text:004071B9                 lea     edx, [eax+1]
.text:004071BC
.text:004071BC loc_4071BC:                             ; CODE XREF: sub_406FC3+1FEj
.text:004071BC                 mov     cl, [eax]
.text:004071BE                 inc     eax
.text:004071BF                 test    cl, cl
.text:004071C1                 jnz     short loc_4071BC
.text:004071C3                 sub     eax, edx
.text:004071C5                 cmp     eax, 0Ch         //输入长度为 12
.text:004071C8                 jnz     short loc_4071D9

要求输入的字符串为12字符的 所以我们需要缩短输入的长度。

a = [0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F]
import itertools
for x1,x2,x3 in itertools.product([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17], repeat=3) :
    tmp = a
    t1 = []
    for i in range(len(a)):
        t1.append(tmp[map[x1][i]])
    t2 = []
    for i in range(len(a)):
        t2.append(t1[map[x2][i]])
    if t2 == a:
        print x1,x2

可以算出来 "0123456789ABCDEFGH" 逆推值为 "210543876BA9EDCHGF"

 

所以 EDAHE450C741GH441E11BH84 的逆推值为 46F911C144FG147E234CFADC (ps:EDAHE450C741GH441E11BH84是 sub_4080DF位置KanXueCrackMe2017字符串加密所得)

 

其中44和11因为相当于没加密可以去除,得到 46F9C1FG147E234CFADC

 

然后还是太长

 

再搜索能不能2字符有没有能用1字符替代的

def check(data):
    newdata = ""
    for i in data:
        if i < 10:
            newdata += chr(ord("0")+i)
        else:
            newdata += chr(ord("A")+i-10)
    data = "46F911C144FG147E234CFADC"   # 34 3
    if newdata[:2] in data:
        print newdata[:2],newdata[2]
    # print newdata,
    return newdata
import itertools
for x1,x2,x3 in itertools.product([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17], repeat=3) :
    tmp = a
    t1 = []
    for i in range(len(a)):
        t1.append(tmp[map[x1][i]])
    t2 = []
    for i in range(len(a)):
        t2.append(t1[map[x2][i]])
    t3 = []
    for i in range(len(a)):
        t3.append(t2[map[x3][i]])
    if t3 == a:
        # print x1,x2,x3
        pt = check([x1,x2,x3]) 

#
#output
#34 3
#DC C 
#FG F

#加上前面推理的 3-5 C-E F-H

因此46F9C1FG147E234CFADC 缩减为 46F9C1H147E25CFAE

 

跑前面的那个进制转换脚本就能够得到flag。


看雪学院推出的专业资质证书《看雪安卓应用安全能力认证 v1.0》(中级和高级)!

收藏
点赞0
打赏
分享
最新回复 (1)
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
绝言 活跃值 2018-5-25 14:03
2
0
看不懂的人路过
游客
登录 | 注册 方可回帖
返回