历经一番唇舌之争,我终于完成了上场任务,还没等我仔细思考微型世界的奥秘,就来到了下一个环节。
环顾四周,我身处的场景不正是熟悉的拳皇吗?人物选择,自然是我最喜欢的八神庵了。
而对方则是成功复活的大蛇一族的最强黑暗力量主人:OROCHI!
生死一刻,凭借我印象中的街机招式究竟能否打败他,我并不能确定。
不过既然来了,也只好一战了。
队长和全部队员就是:大龙猫,如果不算上兔斯基的话。
这只大龙猫不是普通的二次元生物,玩红警3能单挑四家凶残!
此次比赛,再次感谢老婆对我的大力支持,老婆永远是我的女神!
这次图片不秀兔斯基了,我要继续给老婆做好吃的:
小游戏部分
转码部分
总结
if ( get_input() )
{
SetUnhandledExceptionFilter(TopLevelExceptionFilter);
if ( GAME((unsigned __int8 *)name, name_len) )
output("You Win! You are very clever!");
else
output("Game Over");
system("pause");
result = 0;
}
else
{
output("Game Over");
system("pause");
result = 0;
}
for ( i = 0; i < 32; ++i )
{
v4 = read_input();
if ( (v4 < 97 || v4 > 122) && (v4 < 65 || v4 > 90) && (v4 < 48 || v4 > 57) )
{
if ( v4 != 13 && v4 != 10 )
return 0;
name_len = i;
break;
}
name[i] = v4;
}
if ( name_len < 4 || name_len > 16 )
return 0;
output("Please input your KEY: ( : to z )");
for ( j = 0; j < 128; ++j )
{
v3 = read_input();
if ( v3 < ':' || v3 > 'z' )
{
if ( v3 != 13 && v3 != 10 )
return 0;
serial_len = j;
break;
}
serial[j] = v3;
}
if ( !serial_len || serial_len > 128 )
return 0;
dec_len = dec1((int)decode_serial, (int)serial, serial_len);
def dec1(str1):
ans=[]
for i in range(len(str1)/3):
ans.append(ord(str1[i*3])>>2)
ans.append(((ord(str1[i*3])&0b11)<<4)+((ord(str1[i*3+1])&0b11110000)>>4))
ans.append((ord(str1[i*3+1])&0b1111)+((ord(str1[i*3+2])&0b11000000)>>2))
ans.append(ord(str1[i*3+2])&0b00111111)
s=""
for i in ans:
s+=chr(i+ord(":"))
return s
def func1(x, m):
s = x
none_primitive_root = 0
for i in range(1, m):
y = min(x, s)
z = max(x, s)
s = y * y % 17 ^ triangle_at(xor_table, y, z)
......
for ( i = 1; i < 16; ++i )
{
v35 = v38;
v27 = v51;
if ( v38 > (signed int)v51 )
{
v35 = v51;
v27 = v38;
}
v38 = v35 * v35 % 17 ^ table[(unsigned __int8)(v27 + (v35 - 1) * (34 - v35) / 2 - v35)];
if ( v38 == 1 && i != 15 )
{
v51 = (v51 + 1) % 16 + 1;
v38 = 0;
break;
}
}
from base64 import b64decode,b64encode
import os
from functools import reduce
xor_table = [0,3,2,5,4,7,6,9,8,11,10,13,12,15,14,17,0,2,12,14,8,10,20,5,7,1,3,13,15,9,11,0,5,6,8,13,14,3,4,25,11,12,1,2,7,0,19,23,27,31,18,22,26,30,17,21,25,29,0,5,9,14,3,24,12,1,6,10,15,4,0,10,12,1,11,13,6,8,18,7,9,0,10,3,13,6,31,9,2,12,5,0,9,1,14,6,15,7,12,4,0,8,3,11,2,10,29,5,0,7,14,4,11,1,8,0,15,5,3,14,4,0,11,7,2,13,0,28,24,20,0,15,10,0,6,0]
with open('E:/Totoro.exe', 'rb') as f:
f.seek(0x16088, os.SEEK_SET)
bytes_397288 = f.read(65536)
bytes_397288 = [i for i in bytes_397288]
f.seek(0x26088, os.SEEK_SET)
bytes_3A7288 = f.read(256)
bytes_3A7288 = [i for i in bytes_3A7288]
f.seek(0x14E88, os.SEEK_SET)
bytes_396088 = f.read(256)
bytes_396088 = [i for i in bytes_396088]
f.seek(0x14F88, os.SEEK_SET)
bytes_396188 = f.read(4096)
bytes_396188 = [i for i in bytes_396188]
f.seek(0x15F88, os.SEEK_SET)
bytes_417188 = f.read(256)
bytes_417188 = [i for i in bytes_417188]
def quadratic_residues(x, m):
while True:
s = x
for i in range(1, m):
y = s
z = x
if s > x:
y = x
z = s
idx = (z + (y - 1) * (34 - y) // 2 - y)%256
s = (y * y % 17) ^ xor_table[idx]
if s == 1 and i != 15:
x = (x + 1) % 16 + 1
s = 0
break
if s == 1:
break
return x
def _pow(x, m):
s = x
global flag
for i in range(1, m):
y = s
z = x
if s > x:
y = x
z = s
idx = (z + (y - 1) * (34 - y) // 2 - y)%256
s = (y * y % 17) ^ xor_table[idx]
if s == 1 and i != 15:
flag = 1
return s
def triangle_index(y, z):
return z + (y - 1) * (34 - y) // 2 - y
def triangle_at(mat, y, z):
return mat[triangle_index(y, z)]
def get_inv(x):
while True:
s = x
for i in range(1, 16):
y = min(x, s)
z = max(x, s)
s = y * y % 17 ^ triangle_at(xor_table, y, z)
if s == 1 and i != 16 - 1:
x = (x + 1) % 16 + 1
s = 0
break
if s == 1:
break
return x
def pows(x, m):
s = x
none_primitive_root = 0
for i in range(1, m):
y = min(x, s)
z = max(x, s)
s = y * y % 17 ^ triangle_at(xor_table, y, z)
if s == 1 and i != m-1:
none_primitive_root = 1
return s,none_primitive_root
def map_username(username,bytes_417188):
for i in range(len(username) - 1):
ch = username[i + 1]
if i >= 7:
if i >= 10:
if i >= 13:
bytes_417188[i] = ch % 8 + 8
else:
bytes_417188[i] = 7 - ch % 7
else:
bytes_417188[i] = ch % 8 + 8
else:
bytes_417188[i] = 7 - ch % 7
return bytes_417188
def get_idx(a, b, c):
lo = ((b >> 2) ^ ((c << 4) & 0xC0)) ^ ((a << 2) & 0x3C) ^ 0xC7
hi = (c & 3) ^ ((b << 2) & 0xf) ^ 2
x = lo | (hi << 8)
return x
def unknown(a, b, c):
'''a^b^c'''
return bytes_397288[((a + b + c) % 16) | (a << 4) | (b << 8) | (c << 12)]
def check(username, key):
key_len = len(key)
ch = username[0] % 16 + 1
username = map_username(username,bytes_417188)
primitive_root = quadratic_residues(ch,16)
kidx = 0
x = 5
while kidx < key_len:
key_low = key[kidx] % 16 + 1
key_high = (key[kidx]>>4) % 16 + 1
flag = 1
if primitive_root and key_low <= 16 and key_high <=16:
flag = 0
key_low = _pow(primitive_root, key_low)
r2 = quadratic_residues(key_low,16)
key_high = _pow(r2, key_high)
if flag:
break
primitive_root = quadratic_residues(key_high,16)
primitive_flag = (key_high * bytes_396088[username[key_low - 1] - key_high])&0xff
for i in range(key_low, 128):
v4 = int(username[i] == 0)
v5 = (((v4 + bytes_396188[get_idx(username[key_low - 1], username[i], key_high)])%256) * primitive_flag)&0xff
primitive_flag = (((v5 + 1) & int(v5 != 0)) + v5)&0xff
username[key_low - 1] = (username[key_low - 1] + ((((2 * ((primitive_flag + 1) & 1) - 1)&0xff) * key_high)&0xff))&0xff
if not primitive_flag:
break
if not any(username):
return kidx == key_len - 1
key_low_ = (key[kidx] >> 4) % 16 + 1
key_high_ = key[kidx + 1] % 16 + 1
bytes_396088[key_low_ // 2] = (bytes_396088[key_low_ // 2] + key_high_) % 127 + 1
kidx += 1
tmp = unknown(username[2], username[1], username[0])
tmp = unknown(username[4], username[3], tmp)
tmp = unknown(username[6], username[5], tmp)
tmp = unknown(username[8], username[7], tmp)
tmp = unknown(username[10], username[9], tmp)
tmp = unknown(username[12], username[11], tmp)
tmp = unknown(username[14], username[13], tmp)
if tmp:
for i in range(15):
val = bytes_3A7288[tmp | (username[i] << 4)]
if val & 1:
username[i] = val >> 1
break
else:
print(kidx)
fflag = 0
while True:
if username[x] == 1:
username[x] = (username[x] - 1)%256
x = (x + 4) % 15
fflag = 1
break
if username[x] > 1:
break
x = (x + 4) % 15
if fflag == 0:
username[x] = username[x] - ((x * x + 1) % username[x] + 1)
x = (x + 4) % 15
if not reduce(lambda x, y: x | y, username):
break
return False
正确退出应该是循环过每一位序列号经由最后: 判断username数组变换为0时 根据"循环次数==序列号长度-1"来return
在正确序列号变换下经由unknow变换的tmp值每轮都是0(即username数组每一位异或后为0)
import sys
import os
import struct
from base64 import b64decode, b64encode
from capstone import *
from capstone.x86_const import *
from unicorn import *
from unicorn.x86_const import *
def p32(n):
return struct.pack("<I", n)
to = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
base = b':;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxy'
def base64_enc(data):
data = b64encode(data)
res = []
for i in data:
res.append(base[to.index(i)])
return ("".join([chr(i) for i in res])).encode()
def base64_dec(data):
res = []
for i in data:
res.append(to[base.index(i)])
return b64decode("".join([chr(i) for i in res]).encode())
cs = Cs(CS_ARCH_X86, CS_MODE_32)
last_addr = 0
def hook_code(mu, addr, size, user_data):
global last_addr
last_addr = addr
code = mu.mem_read(addr, 10)
ins = next(cs.disasm(code, addr, 1))
disasm = "{:08x}: {} {}".format(addr, ins.mnemonic, ins.op_str)
print(disasm)
mu = None
with open("./Totoro.exe", 'rb') as f:
f.seek(0x400, os.SEEK_SET)
text = f.read(0xf13b - 0x400)
f.seek(0xf320, os.SEEK_SET)
rdata = f.read(0x14c68 - 0xf320)
f.seek(0x14E00, os.SEEK_SET)
data = f.read(0x26C00-0x14E00)
def check(username, key, addr_points=None):
global mu
mu = Uc(UC_ARCH_X86, UC_MODE_32)
text_start , text_end = 0x401000, 0x410000
idata_start, idata_end = 0x410000, 0x410120
rdata_start, rdata_end = 0x410120, 0x416000
data_start , data_end = 0x416000, 0x429000
stack_start, stack_end = 0x7ffa0000, 0x80000000
cache_start, cache_end = 0x100000, 0x110000
stack_curr = 0x7fff0000
mu.mem_map(text_start, data_end - text_start)
mu.mem_write(text_start, text)
mu.mem_write(rdata_start, rdata)
mu.mem_write(data_start, data)
mu.mem_map(stack_start, stack_end - stack_start)
mu.mem_map(cache_start, cache_end - cache_start)
mu.reg_write(UC_X86_REG_ESP, stack_curr)
key_addr = 0x427E38
key_len_addr = 0x427F38
mu.mem_write(key_addr, key)
mu.mem_write(key_addr + len(key), b'\0' * (256 - len(key)))
mu.mem_write(key_len_addr, p32(len(key)))
mu.mem_write(stack_curr + 4, p32(cache_start))
mu.mem_write(cache_start, username)
mu.mem_write(stack_curr + 8, p32(len(username)))
check_addr = 0x401480
check_ret_addr = 0x402088
try:
if not addr_points:
mu.emu_start(check_addr, check_ret_addr)
else:
start = check_addr
for addr in addr_points:
mu.emu_start(start, addr)
mu.emu_start(addr, 0, count=1)
start = mu.reg_read(UC_X86_REG_EIP)
except UcError as e:
return False
return True
username = b'KCTF'
key = [0 for i in range(0x20)]
end = False
for i in range(21):
for ch in range(256):
key[i] = ch
if not check(username, bytes(key), [0x401F00] * (i+1)):
continue
if mu.reg_read(UC_X86_REG_EAX) == 0:
print(i, ch)
break
key[i] = 0x100
if key[i] == 0x100:
break
i += 1
for ch in range(256):
key[i] = ch
if not check(username, bytes(key)):
continue
if mu.reg_read(UC_X86_REG_EAX) == 0:
print(i, ch)
break
print(key)
-------------------------------------------------------------------------------
def dec1(str1):
ans=[]
for i in range(len(str1)/3):
ans.append(ord(str1[i*3])>>2)
ans.append(((ord(str1[i*3])&0b11)<<4)+((ord(str1[i*3+1])&0b11110000)>>4))
ans.append((ord(str1[i*3+1])&0b1111)+((ord(str1[i*3+2])&0b11000000)>>2))
ans.append(ord(str1[i*3+2])&0b00111111)
ans.append(ord(str1[21])>>2)
ans.append((ord(str1[21])&0b11)<<4)
s=""
for i in ans:
s+=chr(i+ord(":"))
return s+"zz"
s=""
final_key=[61, 136, 200, 67, 168, 249, 66, 246, 42, 33, 212, 253, 243, 246, 246, 244, 246, 249, 244, 255, 237, 249]
for i in final_key:
s+=chr(i)
print dec1(s)
【上海第五空间信息科技研究院】(简称:第五空间)是经上海市社会组织管理局批准成立,上海市科协作为业务主管部门的新型研发机构,由翼盾智能科技创始人积聚社会力量发起成立,立足科技事业,支撑国家战略,开展科技研究,推进协同创新。
【杭州安恒信息技术股份有限公司】(简称:安恒信息)成立于2007年,科创板股票代码:688023,一直专注于网络信息安全领域,公司主营业务为网络信息安全产品的研发、生产及销售,并为客户提供专业的网络信息安全服务。公司的产品及服务涉及应用安全、大数据安全、云安全、物联网安全、工业控制安全及工业互联网安全等领域。