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()