shellctf2022-writeup

WP

dragon

很显然,用IDA打开就能看得出来

strcpy((char *)v5, "SHELLCTF{5348454c4c4354467b31355f523376337235316e675f333473793f7d}");

然后,16进制转字符串

from libnum import *
print(n2s(0x5348454c4c4354467b31355f523376337235316e675f333473793f7d))
#b'SHELLCTF{15_R3v3r51ng_34sy?}'

keygen

我们在阅读主程序后发现有一个getString的函数

char *getString()
{
  char *result; // rax

  result = (char *)malloc(0x19uLL);
  strcpy(result, "SHELLCTF{k3ygen_1s_c0oL}");
  return result;
}

so,flag->SHELLCTF{k3ygen_1s_c0oL}

Pulling_the_strings

我们重点关注

 if ( !wcscmp(flag, ws) )

是一个比较的

flag dq offset unk_2008 

我们接着跟进

.rodata:0000000000002008 53                            unk_2008 db  53h ; S     

这里转数组就行,我们提取数据

[0x00000053, 0x00000048, 0x00000045, 0x0000004C, 0x0000004C, 0x00000043, 0x00000054, 0x00000046, 0x0000007B, 0x00000054, 0x00000068, 0x00000034, 0x0000006E, 0x0000006B, 0x00000073, 0x0000005F, 0x00000066, 0x00000030, 0x00000072, 0x0000005F, 0x00000074, 0x00000068, 0x00000065, 0x0000005F, 0x00000066, 0x0000006F, 0x0000006F, 0x00000064, 0x0000007D, 0x00000000]

这里推荐一款好用的IDA插件,LazyIDA,懒人必备

s=[0x00000053, 0x00000048, 0x00000045, 0x0000004C, 0x0000004C, 0x00000043, 0x00000054, 0x00000046, 0x0000007B, 0x00000054, 0x00000068, 0x00000034, 0x0000006E, 0x0000006B, 0x00000073, 0x0000005F, 0x00000066, 0x00000030, 0x00000072, 0x0000005F, 0x00000074, 0x00000068, 0x00000065, 0x0000005F, 0x00000066, 0x0000006F, 0x0000006F, 0x00000064, 0x0000007D, 0x00000000]
print(bytes(s))#b'SHELLCTF{Th4nks_f0r_the_food}\x00'

warmup

 v4 = 1;
    for ( i = 0; i <= 26; ++i )
      v4 = (v6[i] >> 2 == s[i]) & (unsigned __int8)v4;
    if ( v4 == 1 )

这里v4必须等于1,所以v6[i] >> 2 == s[i]必须恒成立

enc=[0]*28
enc[0] = 460
enc[1] = 416
enc[2] = 404
enc[3] = 432
enc[4] = 432
enc[5] = 396
enc[6] = 464
enc[7] = 408
enc[8] = 492
enc[9] = 392
enc[10] = 196
enc[11] = 464
enc[12] = 348
enc[13] = 420
enc[14] = 212
enc[15] = 404
enc[16] = 380
enc[17] = 192
enc[18] = 448
enc[19] = 204
enc[20] = 456
enc[21] = 260
enc[22] = 464
enc[23] = 192
enc[24] = 456
enc[25] = 332
enc[26] = 500
for i in range(len(enc)):
    print(chr(enc[i]>>2),end='')
#shellctf{b1tWi5e_0p3rAt0rS}

tea

我们阅读伪代码后发现有4个函数

分别对应 获取输入,进行奇数偶数分开

进行运算,和再次混合与比较

image-20220813171524679

image-20220813171536715

image-20220813171548035

image-20220813171555478

进行了奇偶拼接,加点数字移动,接着进行了字符串打散再拼接,

第三步逆回去时,有2种思路,可能还更多

第一个就是对字符串开头的shellctf{进行特征排,

image-20220813171951836

第二个就是直接爆字符串,枚举所有可能的字符串

s='R;crc75ihl`cNYe`]m%50gYhugow~34i'

enc=[]
for i in s:
    enc.append(ord(i))
enc=enc*50
# print(enc)
a=len(s)>>1
for k in range(len(s)):
    z=''
    for i in range(len(s)):
        
        if i<a:
            if (enc[k+i]+int(3 * (i // 2)))>=128:
                break
            z+=chr((enc[k+i]+int(3 * (i // 2))))
        else:
            z+=chr((enc[k+i]-i//6))
    if '{' in z and '}' in z:
        print(z)#hlcfT_niiy4DByn}selt{01fN7_n_30d

接下来拼回去就行

one

主要经过3个加密

image-20220813172629857

image-20220813172641378

image-20220813172650387

image-20220813172701029

先拿到密文,我的伪代码被我手修过,你们做的话可能那么好看

image-20220813172755927

转16进制,取最后2位再拆开,这个部分就逆完了

主要是对第二部分

 while ( v9 < len_string )
  {
    *(_QWORD *)s1 = 0LL;
    v20 = 0;
    v10 = 0;
    for ( k = 0; k < v7 && len_string > v9 + k; ++k )
    {
      s1[k] = s[v9 + 48 + k];
      ++v10;
    }
    switch ( v10 )
    {
      case 1:
        if ( !strcmp(s1, "0") )
        {
          v22[opt] = 97;                        // 0
        }
        else if ( !strcmp(s1, "1") )
        {
          v22[opt] = 98;                        // 1
        }
        break;
      case 2:
        if ( !strcmp(s1, "00") )
        {
          v22[opt] = 99;                        // 2
        }
        else if ( !strcmp(s1, "01") )
        {                                       // 3
          v22[opt] = 100;
        }
        else if ( !strcmp(s1, "10") )
        {
          v22[opt] = 101;                       // 4
        }
        else if ( !strcmp(s1, "11") )
        {                                       // 5
          v22[opt] = 102;
        }
        break;
      case 3:
        if ( !strcmp(s1, "000") )
        {
          v22[opt] = 49;                        // 1
        }
        else if ( !strcmp(s1, "001") )
        {
          v22[opt] = 50;                        // 2
        }
        else if ( !strcmp(s1, "010") )
        {
          v22[opt] = 51;                        // 3
        }
        else if ( !strcmp(s1, "011") )
        {
          v22[opt] = 52;                        // 4
        }
        else if ( !strcmp(s1, "100") )
        {
          v22[opt] = 53;                        // 5
        }
        else if ( !strcmp(s1, "101") )
        {
          v22[opt] = 54;                        // 6
        }
        else if ( !strcmp(s1, "110") )
        {
          v22[opt] = 55;                        // 7
        }
        else if ( !strcmp(s1, "111") )
        {                                       // 8
          v22[opt] = 56;
        }
        break;
      default:                                  // 0,无效指令
        v22[opt] = 57;                          // 9
        break;
    }
    v9 += v10;
    ++opt;
    v7 = (v7 + 1) % 4;
  }

我们知道对应指令,却无法得知 具体对应去情况,我一开始想岔了,用递归列举全部情况,然后进行筛选,后来仔细审计发现主要指令是按一定顺序的,用v7再逆回去

剩下的函数就是转2进制,逆回去就行。

enc=[0x00000052, 0x00000091, 0x00000041, 0x00000091, 0x00000036, 0x00000090, 0x00000044, 0x00000090, 0x00000027, 0x00000091, 0x00000042, 0x00000091, 0x00000036, 0x00000091, 0x00000024, 0x00000090, 0x00000026, 0x00000091, 0x00000044, 0x00000090, 0x00000036, 0x00000091, 0x00000038, 0x00000090, 0x00000052, 0x00000091, 0x00000041, 0x00000090, 0x00000052, 0x00000090, 0x00000052, 0x00000090, 0x00000045, 0x00000091, 0x00000048, 0x00000091, 0x00000045, 0x00000091, 0x00000024, 0x00000090, 0x00000026, 0x00000091, 0x00000027, 0x00000090, 0x00000046, 0x00000091, 0x00000027, 0x00000090, 0x00000058, 0x00000090, 0x00000047, 0x00000090, 0x00000035, 0x00000090, 0x00000027, 0x00000090, 0x00000037, 0x00000091, 0x00000044, 0x00000090, 0x00000046, 0x00000090, 0x00000044, 0x00000090, 0x00000032, 0x00000091, 0x00000046, 0x00000090, 0x00000052, 0x00000090, 0x00000027, 0x00000090, 0x00000057, 0x00000091, 0x00000044, 0x00000091, 0x00000036, 0x00000090, 0x00000047, 0x00000090, 0x00000058, 0x00000090, 0x00000042, 0x00000090, 0x00000052, 0x00000091, 0x00000056, 0x00000090, 0x00000046, 0x00000090, 0x00000046, 0x00000091, 0x00000054]
command=[]
for i in range(len(enc)):
    Head=str(hex(enc[i]))[2:3]
    Next=str(hex(enc[i]))[3:]
    command.append(int(Head))
    command.append(int(Next))
o=''
v7=2
for i in range(len(command)):
    if v7==1:
        if command[i]==0:
            o+='0'
        elif command[i]==1:
            o+='1'
        else:
            print('Command Wrong!!')
    elif v7==2:
        if command[i]==2:
            o+='00'
        elif command[i]==3:
            o+='01'
        elif command[i]==4:
            o+='10'
        elif command[i]==5:
            o+='11'
        else:
            print('Command Wrong!!')
    elif v7==3:
        if command[i]==1:
            o+='000'
        elif command[i]==2:
            o+='001'
        elif command[i]==3:
            o+='010'
        elif command[i]==4:
            o+='011'
        elif command[i]==5:
            o+='100'
        elif command[i]==6:
            o+='101'
        elif command[i]==7:
            o+='110'
        elif command[i]==8:
            o+='111'
        else:
            print('Command Wrong!!')
    v7=(v7+1)%4
str_1=[]
print(len(o))
print(o)
for i in range(len(o)//8):
        s=o[i*8:(i+1)*8]
        bin_string='0b'
        for j in range(len(s)-1,-1,-1):
            bin_string+=s[j]
        str_1.append(eval(bin_string))
print(bytes(str_1))#b'shellctf{s0Me_b4S3_c0nVer51on5_4_U\xbd'

最后一位没抢救过来

我手补一下

shellctf{s0Me_b4S3_c0nVer51on5_4_U}

switf


加密key是"EULERSNUMBER"

密文是wbppcugz{F4zp0i5_w3l1p5_sW_4_xHhO7j0r}

维吉尼亚,直接解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值