首页
社区
课程
招聘
KCTF2019Q4 第三题 街机少年
2019-12-7 11:16 3621

KCTF2019Q4 第三题 街机少年

2019-12-7 11:16
3621
1. base64
字符集: 0x3A-0x7A
src: 00aaaaaa 00bbcccc 00eedddd 00ffffff
dst: aaaaaabb ccccdddd eeffffff

2. F5的结果抠出来爆破
对sn的每个字节, 设置好条件, 每次得到的结果都是唯一的

3. 脚本

def hex2bin(s):
    return s.decode('hex')


def bin2hex(s):
    return s.encode('hex').upper()


def load_file(filename):
    f = open(filename, 'rb')
    s = f.read()
    f.close()
    return s


def save_file(filename, s):
    f = open(filename, 'wb')
    f.write(s)
    f.close()
    return


def b64_encode(s):
    r = ''
    for i in range(0, len(s), 3):
        ss = s[i:i+3]
        src_len = len(ss)
        src = [0] * 3
        dst = [0] * 4
        for j in range(src_len):
            src[j] = ord(ss[j])
        dst[0] = src[0] >> 2
        dst[1] = ((src[0] & 3) << 4) | (src[1] >> 4)
        dst[2] = (src[1] & 0x0F) | ((src[2] >> 6) << 4)
        dst[3] = src[2] & 0x3F
        if src_len == 1:
            dst[2] = 0x40
            dst[3] = 0x40
        if src_len == 2:
            dst[3] = 0x40
        for j in range(4):
            r += chr(dst[j] + 0x3A)
    return r


def b64_decode(s):
    r = ''
    for i in range(0, len(s), 4):
        dst_len = 3
        src = [0] * 4
        dst = [0] * 3
        for j in range(4):
            v = ord(s[i+j])
            if v == 0x7A:
                dst_len -= 1
            src[j] = v - 0x3A
        # src: 00aaaaaa 00bbcccc 00eedddd 00ffffff
        # dst: aaaaaabb ccccdddd eeffffff
        dst[0] = ((src[0] << 2) & 0xFC) | (src[1] >> 4)
        dst[1] = ((src[1] << 4) & 0xF0) | (src[2] & 0x0F)
        dst[2] = ((src[2] << 2) & 0xC0) | src[3]
        for j in range(dst_len):
            r += chr(dst[j])
    return r


def sort_ascending(a, b):
    if a <= b:
        return a, b
    else:
        return b, a


def fn1(v, bound=None):
    buf_const_416000 = [
        0x00, 0x03, 0x02, 0x05, 0x04, 0x07, 0x06, 0x09, 0x08, 0x0B, 0x0A, 0x0D, 0x0C, 0x0F, 0x0E, 0x11,
        0x00, 0x02, 0x0C, 0x0E, 0x08, 0x0A, 0x14, 0x05, 0x07, 0x01, 0x03, 0x0D, 0x0F, 0x09, 0x0B,
        0x00, 0x05, 0x06, 0x08, 0x0D, 0x0E, 0x03, 0x04, 0x19, 0x0B, 0x0C, 0x01, 0x02, 0x07,
        0x00, 0x13, 0x17, 0x1B, 0x1F, 0x12, 0x16, 0x1A, 0x1E, 0x11, 0x15, 0x19, 0x1D,
        0x00, 0x05, 0x09, 0x0E, 0x03, 0x18, 0x0C, 0x01, 0x06, 0x0A, 0x0F, 0x04,
        0x00, 0x0A, 0x0C, 0x01, 0x0B, 0x0D, 0x06, 0x08, 0x12, 0x07, 0x09,
        0x00, 0x0A, 0x03, 0x0D, 0x06, 0x1F, 0x09, 0x02, 0x0C, 0x05,
        0x00, 0x09, 0x01, 0x0E, 0x06, 0x0F, 0x07, 0x0C, 0x04,
        0x00, 0x08, 0x03, 0x0B, 0x02, 0x0A, 0x1D, 0x05,
        0x00, 0x07, 0x0E, 0x04, 0x0B, 0x01, 0x08,
        0x00, 0x0F, 0x05, 0x03, 0x0E, 0x04,
        0x00, 0x0B, 0x07, 0x02, 0x0D,
        0x00, 0x1C, 0x18, 0x14,
        0x00, 0x0F, 0x0A,
        0x00, 0x06,
        0x00
    ]
    v51 = v
    end = 16 if bound is None else int(bound)
    while True:
        v38 = v51
        for i in range(1, end):
            v_smaller, v_bigger = sort_ascending(v38, v51)
            idx = v_bigger - v_smaller + (v_smaller - 1) * (34 - v_smaller) / 2
            v38 = ((v_smaller * v_smaller) % 17) ^ buf_const_416000[idx]
            if v38 == 1 and i != (end - 1) and bound is None:
                v51 = (v51 + 1) % 16 + 1
                v38 = 0
                break
        if bound is not None:
            return v38
        elif v38 == 1:
            return v51


def t1(v, low, high):
    v = fn1(v, low)
    low = v
    v = fn1(v)
    v = fn1(v, high)
    high = v
    v = fn1(v)
    return v, low, high


base_dir = 'D:\\work\\2019\\pediy_Q4\\3\\'
buf_const_416188 = [0] * 4096
buf_const_417288 = [0] * 65536
buf_const_427288 = [0] * 256


def fn_402090(a, b, c):
    v = 0
    v |= (b & 3) << 10
    v |= (c & 3) << 8
    v |= ((c >> 2) & 3) << 6
    v |= (a & 0x0F) << 2
    v |= (b >> 2) & 3
    v ^= 0x2C7
    return v


def fn2(buf_user_417188, buf_var_416088, low, high):
    low_1 = low - 1
    v48 = high * buf_var_416088[(buf_user_417188[low_1] - high)]
    v48 &= 0xFF

    for n in range(low_1 + 1, 128):
        v5 = buf_const_416188[fn_402090(buf_user_417188[low_1], buf_user_417188[n], high)]
        if buf_user_417188[n] == 0:
            v5 += 1
        v5 *= v48
        v5 &= 0xFF
        v48 = ((v5 + 1) & (v5 != 0)) + v5
        v48 &= 0xFF
    if (v48 % 2) == 0:
        buf_user_417188[low_1] += high
        buf_user_417188[low_1] &= 0xFF
        return False
    else:
        buf_user_417188[low_1] -= high
        buf_user_417188[low_1] &= 0xFF
        return True


def init_consts(new=False):
    s = load_file(base_dir + 'buf_const_416188.txt')
    for i in range(len(s)):
        buf_const_416188[i] = ord(s[i])

    s = load_file(base_dir + 'buf_const_417288.txt')
    for i in range(len(s)):
        buf_const_417288[i] = ord(s[i])

    s = load_file(base_dir + 'buf_const_427288%s.txt' % ('_new' if new else ''))
    for i in range(len(s)):
        buf_const_427288[i] = ord(s[i])

    return


def is_ary_all_zero(ary, n):
    for i in range(n):
        if ary[i] != 0:
            return False
    return True


def const_65536_map(a, b, c):
    idx = 0
    idx |= (c + b + a) & 0x0F
    idx |= c << 4
    idx |= b << 8
    idx |= a << 12
    v = buf_const_417288[idx]
    return v


def save_buf_const_427288_new():
    init_consts()
    s = ''
    for i in range(256):
        v = buf_const_427288[i]
        if (v & 1) == 0:
            s += chr(0xFF)
        else:
            s += chr(v >> 1)
    save_file(base_dir + 'buf_const_427288_new.txt', s)
    return


def init_buf_user(buf_user_417188, username):
    for i in range(len(username)):
        v = ord(username[i])
        if i < 7:
            buf_user_417188[i] = 7 - (v % 7)
        elif i < 10:
            buf_user_417188[i] = 8 + (v % 8)
        elif i < 13:
            buf_user_417188[i] = 7 - (v % 7)
        else:
            buf_user_417188[i] = 8 + (v % 8)
    return


def test0():
    init_consts(new=True)
    username = 'f3a25f8b29bb9cbc'
    sn = b64_decode('JXg@vwrpfoLbRcxvdYrvv[kyRSso')
    # username = 'KCTF'
    # sn = b64_decode('IRrBJtrsJi@dBWnwvyppwIpswIygxJzz')
    buf_user_417188 = [
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x05, 0x06, 0x07, 0x0E, 0x0F, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    ]
    init_buf_user(buf_user_417188, username[1:])
    buf_var_416088 = [
        0x09, 0x1A, 0x0D, 0x04, 0x1F, 0x3E, 0x28, 0x47, 0x4B, 0x6F, 0x7D, 0x85, 0xA5, 0xCE, 0xFF, 0x05,
        0x24, 0x4B, 0x6A, 0x8C, 0xA7, 0xE6, 0x19, 0x56, 0x6B, 0xB6, 0xC0, 0x04, 0x48, 0x8B, 0xC4, 0x14,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    ]

    v51 = fn1(ord(username[0]) % 16 + 1)
    v44 = 5
    print(buf_user_417188[:15])
    for i_sn in range(len(sn)):
        low = (ord(sn[i_sn]) & 0x0F) + 1
        high = ((ord(sn[i_sn]) >> 4) & 0x0F) + 1
        # print('v51: %d, low: %d, high: %d' % (v51, low, high))
        v51, low, high = t1(v51, low, high)

        if fn2(buf_user_417188, buf_var_416088, low, high):
            print('sub [%02Xh], %d' % (low-1, high))
        else:
            # never goes here
            print('add [%02Xh], %d' % (low-1, high))
        print(buf_user_417188[:15])

        if is_ary_all_zero(buf_user_417188, 128):
            print('ok')
            return

        low = ((ord(sn[i_sn]) >> 4) & 0x0F) + 1
        high = (ord(sn[i_sn + 1]) & 0x0F) + 1
        idx = low >> 1
        # only affects 1:1+8 bytes
        buf_var_416088[idx] += high
        buf_var_416088[idx] = buf_var_416088[idx] % 127 + 1

        v = buf_user_417188[0]
        for i in range(1, 15, 2):
            v = const_65536_map(v, buf_user_417188[i], buf_user_417188[i + 1])
        if v:
            # never goes here
            for i in range(15):
                k = buf_const_427288[(buf_user_417188[i] << 4) | v]
                if k != 0xFF:
                    print('mov [%02Xh], %d' % (i, k))
                    buf_user_417188[i] = k
                    break
        else:
            while True:
                v = v44
                v44 = (v44 + 4) % 15
                if buf_user_417188[v] == 1:
                    print('dec [%02Xh]' % v)
                    buf_user_417188[v] -= 1
                    break
                if buf_user_417188[v] > 1:
                    v2 = (v * v + 1) % buf_user_417188[v] + 1
                    print('sub2 [%02Xh], %d' % (v, v2))
                    buf_user_417188[v] -= v2
                    break
        print(buf_user_417188[:15])
    return


def probe_calc(username, sn, buf_user_417188, buf_var_416088):
    v51 = fn1(ord(username[0]) % 16 + 1)
    init_buf_user(buf_user_417188, username[1:])

    v44 = 5
    for i_sn in range(len(sn)):
        low = (sn[i_sn] & 0x0F) + 1
        high = ((sn[i_sn] >> 4) & 0x0F) + 1
        v51, low, high = t1(v51, low, high)
        fn2(buf_user_417188, buf_var_416088, low, high)
        if (i_sn + 1) >= len(sn):
            break
        low = ((sn[i_sn] >> 4) & 0x0F) + 1
        high = (sn[i_sn + 1] & 0x0F) + 1
        idx = low >> 1
        buf_var_416088[idx] += high
        buf_var_416088[idx] = buf_var_416088[idx] % 127 + 1

        while True:
            v = v44
            v44 = (v44 + 4) % 15
            if buf_user_417188[v] == 1:
                buf_user_417188[v] -= 1
                break
            if buf_user_417188[v] > 1:
                v2 = (v * v + 1) % buf_user_417188[v] + 1
                buf_user_417188[v] -= v2
                break
    return v51, v44


def probe_once(username, sn):
    for low in range(1, 17):
        for high in range(1, 17):
            tmp_user = [
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x05, 0x06, 0x07, 0x0E, 0x0F, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            ]
            tmp_var = [
                0x09, 0x1A, 0x0D, 0x04, 0x1F, 0x3E, 0x28, 0x47, 0x4B, 0x6F, 0x7D, 0x85, 0xA5, 0xCE, 0xFF, 0x05,
                0x24, 0x4B, 0x6A, 0x8C, 0xA7, 0xE6, 0x19, 0x56, 0x6B, 0xB6, 0xC0, 0x04, 0x48, 0x8B, 0xC4, 0x14,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            ]
            v51, v44 = probe_calc(username, sn, tmp_user, tmp_var)
            if is_ary_all_zero(tmp_user, 128):
                return False
            if len(sn) > 0:
                next_low = (sn[-1] >> 4) + 1
                next_high = low
                idx = next_low >> 1
                tmp_var[idx] += next_high
                tmp_var[idx] = tmp_var[idx] % 127 + 1
                while True:
                    v = v44
                    v44 = (v44 + 4) % 15
                    if tmp_user[v] == 1:
                        tmp_user[v] -= 1
                        break
                    if tmp_user[v] > 1:
                        v2 = (v * v + 1) % tmp_user[v] + 1
                        tmp_user[v] -= v2
                        break
            new_v, new_low, new_high = t1(v51, low, high)
            if fn2(tmp_user, tmp_var, new_low, new_high):
                v = tmp_user[0]
                for i in range(1, 15, 2):
                    v = const_65536_map(v, tmp_user[i], tmp_user[i + 1])
                if v == 0:
                    print('[%d]: %X%X' % (len(sn), high - 1, low - 1))
                    sn.append((high - 1 << 4) | (low - 1))
                    return True
    return False


def probe():
    init_consts(new=True)
    sn = []
    username = 'f3a25f8b29bb9cbc'
    username = 'KCTF'
    while True:
        if not probe_once(username, sn):
            break
    s = ''
    for i in range(len(sn)):
        s += chr(sn[i])
    s = b64_encode(s)
    print s
    return


def test():
    # test0()
    probe()
    return


test()


[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞2
打赏
分享
最新回复 (1)
雪    币: 19
活跃值: (128)
能力值: ( LV9,RANK:146 )
在线值:
发帖
回帖
粉丝
wendax 2019-12-11 17:21
2
0
神 你终于回来了 我永远崇拜你
游客
登录 | 注册 方可回帖
返回