MOECTF-RE方向的一些wp

哥们刚学ctf,看了看大家都说WEB和MISC上手更快,但是其他题我实在做不走了,于是去RE看了看,虽然做的不多,但还是觉得挺有趣的。

话不多说,直接看题:

1)base_64

顾名思义,考的就是base_64的相关内容,打开附件得到源码,很简单:

先去在线网站把.pyc文件反编译成.py文件:

https://toolkk.com/tools/pyc-decomplie#google_vignette

得到如下代码:

import base64
from string import *
str1 = 'yD9oB3Inv3YAB19YynIuJnUaAGB0um0='
string1 = 'ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba0123456789+/'
string2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
flag = input('welcome to moectf\ninput your flag and I wiil check it:')
enc_flag = base64.b64encode(flag.encode()).decode()
enc_flag = enc_flag.translate(str.maketrans(string2, string1))
if enc_flag == str1:
    print('good job!!!!')
else:
    print('something wrong???')
    exit(0)
# okay decompiling /tmp/64e8b71bb111a.pyc

看了看就知道,把flag进行如上操作一步步得到最后的结果,那么我们就逆向分析,一步步给它反推回去,就能拿到flag了。

写个简单的脚本:

import base64
from string import *
str1 = 'yD9oB3Inv3YAB19YynIuJnUaAGB0um0='
string1 = 'ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba0123456789+/'
string2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'


flag_str1 = str1.translate(str.maketrans(string1,string2))
flag_original_bytes = flag_str1.encode()
flag_final_bytes = base64.b64decode(flag_original_bytes)
flag_final_str = flag_final_bytes.decode()

print(flag_final_str)

运行即得到flag:

2)UPX!

看了下标题,然后去搜了搜,发现需要脱壳,那么我们就去kali里脱壳,然后再在IDA里分析就完事了。

脱壳完毕,直接再复制回windows,用IDA64打开并解析:

(刚用IDA的时候,根本看不懂,边搜边硬做的......QAQ)

搜索关键字moectf找到关键函数体,然后f5查看代码:

 这就是关键函数,看了看是个很简单的异或,我们直接写个十六进制脚本就能解出来:

key = [0x0A, 0x08, 0x02, 0x04, 0x13, 0x01, 0x1C, 0x57, 0x0F, 0x38, 
  0x1E, 0x57, 0x12, 0x38, 0x2C, 0x09, 0x57, 0x10, 0x38, 0x2F, 
  0x57, 0x10, 0x38, 0x13, 0x08, 0x38, 0x35, 0x02, 0x11, 0x54, 
  0x15, 0x14, 0x02, 0x38, 0x32, 0x37, 0x3F, 0x46, 0x46, 0x46, 
  0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00]

for i in range(0,len(key)):
    key[i] = key[i] ^ 0x67

print("".join(chr(x) for x in key))

 运行得到flag~~

3)Xor

简单的Xor逆向,直接拿到IDA里一搜main就知道主要函数了:

 写个脚本解决:

key = [0x54, 0x56, 0x5C, 0x5A, 0x4D, 0x5F, 0x42, 0x60, 0x56, 0x4C, 0x66, 0x52, 0x57, 0x09, 0x4E, 0x66, 0x51, 0x09, 0x4E, 0x66, 0x4D, 0x09, 0x66, 0x61, 0x09, 0x6B, 0x18, 0x44]


for i in range(0,len(key)):
	key[i] = key [i] ^ 0x39

print("".join(chr(x) for x in key))

运行得到flag:

4)ANDROID

据题目说是基于Java的,用的工具是JADX:

我们先在手机上安装看看:

随便乱输提交,给了个反馈:“长度不对哦”

那么就好搜了哼哼~~

在下好的JADX中打开这个文件:

再打开需要逆向分析的文件,然后文本搜索关键信息“长度不对哦”找到主要函数:

开始觉得很复杂,后面一看才发现换汤不换药,还是异或。

写个脚本也出来了:

#re:    1、把enc[i]每一项与key[i%key.length()]进行异或操作  得到字节数组
#       2、把字节数组变成字符串

#enc = [25, 7, 0, 14, 27, 3, 16, '/', 24, 2, '\t', ':', 4, 1, ':', '*', 11, 29, 6, 7, '\f', '\t', '0', 'T', 24, ':', 28, 21, 27, 28, 16]
#key = ['t', 'h', 'e', 'm', 'o', 'e', 'k', 'e', 'y']


#转十六进制
enc_hex = [0x19, 0x7, 0x0, 0xe, 0x1b, 0x3, 0x10, 0x2f, 0x18, 0x2, 0x9, 0x3a, 0x4, 0x1, 0x3a, 0x2a, 0xb, 0x1d, 0x6, 0x7, 0xc, 0x9, 0x30, 0x54, 0x18, 0x3a, 0x1c, 0x15, 0x1b, 0x1c, 0x10]
key_hex = [0x74, 0x68, 0x65, 0x6d, 0x6f, 0x65, 0x6b, 0x65, 0x79]


flag_bytes = [0] * len(enc_hex)
for i in range(0,len(enc_hex)):
    flag_bytes[i] = enc_hex[i] ^ key_hex[i % len(key_hex)]

flag = "".join(chr(x) for x in flag_bytes) 

print(flag)

运行得到flag辣:

 (未完待续......)

 5)RC4

有点抽象,多余的就不写了,直接搜索关键字moectf找到关键函数:

sub_14007555C(&unk_1401A7007);
  memset(v5, 0, sizeof(v5));
  memset(v6, 0, sizeof(v6));
  strcpy(v7, "moectf2023");
  v8 = 0;
printf("welcome to moectf!!!");
printf("This is a very common algorithm ");
printf("show your flag:");
scanf("%s", arr);
  if ( size(arr) == 37 )
  {
    sub_140075052((unsigned int)v5, (unsigned int)v6, (unsigned int)arr, 38, (__int64)v7, 10);
    for ( j = 0; (unsigned __int64)j < 0x26; ++j )
    {
      if ( byte_140196000[j] == (unsigned __int8)arr[j] )
        ++v8;
    }
  }
  if ( v8 == 37 )
    sub_140073973("right!flag is your input!");
  else
    sub_140073973("try again~");
  sub_140074BCF(v3, &unk_140162100);
  return 0i64;
}



unsigned char ida_chars[] =
{
  0x1B, 0x9B, 0xFB, 0x19, 0x06, 0x6A, 0xB5, 0x3B, 0x7C, 0xBA, 
  0x03, 0xF3, 0x91, 0xB8, 0xB6, 0x3D, 0x8A, 0xC1, 0x48, 0x2E, 
  0x50, 0x11, 0xE7, 0xC7, 0x4F, 0xB1, 0x27, 0xCF, 0xF3, 0xAE, 
  0x03, 0x09, 0xB2, 0x08, 0xFB, 0xDC, 0x22, 0x00
};

下面是我提取出来的数据,本来我想自己逆出个脚本来的:

import numpy as np

# int result;
# int i;
# int j;
# int v9;
# int v10;
# int v11;
# char v12;
# char v13;
# int v14;
a1 = np.zeros(256)
a2 = np.zeros(256)
a3 = [0x1B, 0x9B, 0xFB, 0x19, 0x06, 0x6A, 0xB5, 0x3B, 0x7C, 0xBA, 0x03, 0xF3, 0x91, 0xB8, 0xB6, 0x3D, 0x8A, 0xC1, 0x48, 0x2E, 0x50, 0x11, 0xE7, 0xC7, 0x4F, 0xB1, 0x27, 0xCF, 0xF3, 0xAE, 0x03, 0x09, 0xB2, 0x08, 0xFB, 0xDC, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
for x in a3:
    x = chr(x) #转成字符数组
a4 = 38
a5 = "moectf2023"
a5 = list(a5)
a6 = 10

v10 = 0;
v14 = 0;

for i in range(0, 256):
    a1[i] = i;
    a2[i] = ord(a5[i % a6]);

for j in range(0, 256):
    v10 = (a2[j] + a1[j] + j) % 256;

    # 交换
    v10 = int(v10)
    j = int(j)
    v12 = a1[v10];
    a1[v10] = a1[j];
    a1[j] = v12;

    result = j + 1;

i = 0;
j = 0;
k = 0;
while (a4):

    i = (i + 1) % 256;
    j = (a1[i] + j) % 256;

    # 交换
    j = int(j)
    i = int(i)
    v13 = a1[j];
    a1[j] = a1[i];
    a1[i] = v13;

    a1[i] = int(a1[i])
    a1[j] = int(a1[j])
    k = int(a1[j] + a1[i])
    a3[v14] ^= a1[k] % 256;
    v14 = v14 + 1;
    result = --a4;

print(a3)

但是有问题,所以我去查了下CTFwiki,对应的RC4解码知识,

传送门:常见加密算法和编码识别 - CTF Wiki (ctf-wiki.org)

然后我就用了它给的脚本,真好用hhh~~~

import base64
def rc4_main(key = "init_key", message = "init_message"):
    print("RC4解密主函数调用成功")
    print('\n')
    s_box = rc4_init_sbox(key)
    crypt = rc4_excrypt(message, s_box)
    return crypt
def rc4_init_sbox(key):
    s_box = list(range(256))
    print("原来的 s 盒:%s" % s_box)
    print('\n')
    j = 0
    for i in range(256):
        j = (j + s_box[i] + ord(key[i % len(key)])) % 256
        s_box[i], s_box[j] = s_box[j], s_box[i]
    print("混乱后的 s 盒:%s"% s_box)
    print('\n')
    return s_box
def rc4_excrypt(plain, box):
    print("调用解密程序成功。")
    print('\n')
    plain = base64.b64decode(plain.encode('utf-8'))
    plain = bytes.decode(plain)
    res = []
    i = j = 0
    for s in plain:
        i = (i + 1) % 256
        j = (j + box[i]) % 256
        box[i], box[j] = box[j], box[i]
        t = (box[i] + box[j]) % 256
        k = box[t]
        res.append(chr(ord(s) ^ k))
    print("res用于解密字符串,解密后是:%res" %res)
    print('\n')
    cipher = "".join(res)
    print("解密后的字符串是:%s" %cipher)
    print('\n')
    print("解密后的输出(没经过任何编码):")
    print('\n')
    return cipher
a=[0x1B, 0x9B, 0xFB, 0x19, 0x06, 0x6A, 0xB5, 0x3B, 0x7C, 0xBA, 0x03, 0xF3, 0x91, 0xB8, 0xB6, 0x3D, 0x8A, 0xC1, 0x48, 0x2E, 0x50, 0x11, 0xE7, 0xC7, 0x4F, 0xB1, 0x27, 0xCF, 0xF3, 0xAE, 0x03, 0x09, 0xB2, 0x08, 0xFB, 0xDC, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] #cipher
key="moectf2023"
s=""
for i in a:
    s+=chr(i)
s=str(base64.b64encode(s.encode('utf-8')), 'utf-8')
rc4_main(key, s)

这个甚至能重复利用,只需要把a、key替换就能反复利用了,原理也不介绍了,CTFwiki介绍的很清楚。

运行拿到flag:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值