[ctf.show.reverse] BJDCTF2020 encode

这题有错

UPX脱壳后,可以看到逻辑比较简单

先是读入21字节的flag然后进行自定义码表的base64编码,然后与key进行一次异或。再作个加密后与给定串比较

  strcpy(v8, "Flag{This_a_Flag}");
  v6 = strlen(v8);
  strcpy(v9, "E8D8BD91871A1E56F53F4889682F96142AF2AB8FED7ACFD5E");
  puts((int)"Please input your flag:");
  read(0, &v9[50], 256);
  if ( strlen(&v9[50]) != 21 )                  // flag长21
    exit(0);
  v3 = s_base64encode((int)&v9[50]);            // 非标码表base64编码
  strcpy((int)&v8[18], v3);
  v7 = strlen(&v8[18]);
  for ( i = 0; i < v7; ++i )
    v8[i + 18] ^= v8[i % v6];                   // 与Flag{This_a_Flag}异或
  crypto((int)&v8[18], v7, (int)v8, v6);        // RC4 ???
  if ( !strcmp___() )
    exit(0);
  puts((int)"right!");

加密方法从网上搜的说叫RC4运行,但这里显然与常用的RC4不同。这是从网上搜到的源程序。很明显它是等长加密的。而且生成码表后只对明文进行一次异或运算。

static void rc4_init(unsigned char* s_box, unsigned char* key, unsigned int key_len)
{
    unsigned char Temp[256];
    int i;
    for (i = 0; i < 256; i++)
    {
        s_box[i] = i;//顺序填充S盒
        Temp[i] = key[i%key_len];//生成临时变量T
    }
    int j = 0;
    for (i = 0; i < 256; i++)//打乱S盒
    {
        j = (j + s_box[i] + Temp[i]) % 256;
        unsigned char tmp = s_box[i];
        s_box[i] = s_box[j];
        s_box[j] = tmp;
    }
}
 
void rc4_crypt(unsigned char* data, unsigned int data_len, unsigned char* key, unsigned int key_len)
{
    unsigned char s_box[256];
    rc4_init(s_box, key, key_len);
    unsigned int i = 0, j = 0, t = 0;
    unsigned int Temp;
    for (Temp = 0; Temp < data_len; Temp++)
    {
        i = (i + 1) % 256;
        j = (j + s_box[i]) % 256;
        unsigned char tmp = s_box[i];
        s_box[i] = s_box[j];
        s_box[j] = tmp;
        t = (s_box[i] + s_box[j]) % 256;
        data[Temp] ^= s_box[t];
    }
}

网上搜到一个WP显然XXX,给出了4个网上的RC4解密网站,其实肯定解不了,因为就不是一回事。用这个加密方法对flag加密后应该是这个,flag是21字节base64后是28再转16进制是56。题目里给的长度都不对而且给了一个16进制编码后的。(出错的地方是转16进制的时候把01这样的转成1了)

E8D8BD91871A010E560F53F4889682F961420AF2AB08FED7ACFD5E00

用这个密文写的解密程序

#UPX ex.

key0 = b'Flag{This_a_Flag}'
#这个密文解密后得不到flag长度都不对
#E8D8BD91871A1E56F53F4889682F96142AF2AB8FED7ACFD5E
#E8D8BD91871A010E560F53F4889682F961420AF2AB08FED7ACFD5E00 正确的密文
c = bytes.fromhex('E8D8BD91871A010E560F53F4889682F961420AF2AB08FED7ACFD5E00')
#key2 sub_8048CC2
v9 = [i for i in range(256)]
v8 = (key0*50)[:256]

j = 0
for i in range(256):
    j = (v9[i] + j + v8[i]) %256
    v9[i],v9[j] = v9[j],v9[i]

tab = [0]*28
i,j = 0,0
for t in range(28):
    i = (i+1) % 256
    j = (v9[i]+ j) % 256
    v9[i],v9[j] = v9[j],v9[i]
    tab[t] = v9[(v9[i] + v9[j])%256]


#先解密
c = [tab[i]^v for i,v in enumerate(c)]
#再与key0作异或
c = bytes([v8[i]^c[i] for i in range(len(c))])
#再进行转表到标准base64
s1 = b'0123456789+/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ='
s2 = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
c = bytes([s2[s1.index(i)] for i in c])
#base64解码
from base64 import b64decode
print(b64decode(c))

#BJD{0v0_Y0u_g07_1T!}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值