Buuoj-reverse-ACTF新生赛2020_usualCrypt

1. 分析文件类型,是否加壳

将文件扔进exeinfope中查看,发现是无壳的32位可执行程序
https://i.loli.net/2021/02/23/slTayZSr85wvdiI.png

2. 使用IDA对文件进行分析

  • 此处的main函数代码较为简单,其逻辑为接收输入,用 sub_401080 函数对其进行处理,处理后的结果若与byte_40E0E4 处字符串相同,则该输出即为flag。所以我们的重点应该放在 sub_401080 函数上。
    https://i.loli.net/2021/02/23/z9M4ufKaDXNsmIq.png
  • 分析 sub_401080 函数的逻辑
    https://i.loli.net/2021/02/23/gAzWKk8td7SELqb.png
    https://i.loli.net/2021/02/23/UHZrzyEBVdslx52.png
    从上面两幅图的分析中可以得到,函数sub_401080的作用就是进行base64编码只是它还将原本的编码表做了一个简单的处理。所以根据以上分析,我们可以写出解码代码。

解题

# 大小写转化
def convert_little_big(s):
    ans = ''
    for c in s:
        if c >= 'a' and c <= 'z':
            ans += chr(ord(c) - ord('a') + ord('A'))
        elif c >= 'A' and c <= 'Z':
            ans += chr(ord(c) - ord('A') + ord('a'))
        else:
            ans += c
    return ans

# 处理base编码表
def shift(s):
    idx = 6
    s = list(s)
    for idx in range(6, 15):
        s[idx], s[idx + 10] = s[idx + 10], s[idx]
    return ''.join(s)

'''
base64解码
因为编码后无 '='
所以可以知道原字符串的长度必然是3的倍数
所以我们这里不需要去处理余数的情况
'''
def solve(s, base):
    flag = [0] * (len(s) * 3 // 4)
    idx = 0
    for i in range(0, len(s), 4):
        a, b, c, d = base.index(s[i]), base.index(s[i+1]), base.index(s[i+2]), base.index(s[i+3])
        flag[idx] = (a << 2) | ((b >> 4) & 0x3)
        flag[idx + 1] = ((b & 0xf) << 4) | ((c >> 2) & 0xf)
        flag[idx + 2] = ((c & 0x3) << 6) | (d & 0x3f)
        idx += 3
    print(flag)
    print(''.join(chr(c) for c in flag)) 

if __name__ == '__main__':
    base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    base = shift(base)
    print(base)
    res = 'zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9'
    res = convert_little_big(res)
    print(len(res))
    solve(res, base)

flag{bAse64_h2s_a_Surprise}

posted @ 2021-02-23 22:03  bunner  阅读(63)  评论(0编辑  收藏  举报