现在调出大楼布局图,争分夺秒找到最快速的逃离路线,逃出生天吧!
你们逃出封闭的那一楼层,但最后的决战才刚刚拉开帷幕……只有攻破控制一切的Norns,才有可能让全球的失控仿生人恢复正常。
你们搭乘磁悬浮电梯赶往位于研究所顶层的机房,超级计算机Norns的本体就在那里。
希莉娅告诉你和肖恩,为了保障城市正常运转,Norns核心机组所在的机房门是特制的,比旧日银行金库的门还要更坚如磐石,只有核心研发人员才能通过身份认证和权限卡的双重认证来开启大门。
希莉娅猜测这就是Norns抹去自己所有个人信息的原因之一,为了让自己无法进入这扇大门……于是你和肖恩制定了一个作战计划,你入侵Norns为佯攻,肖恩则趁机恢复希莉娅的个人信息。
虽然无法完全攻破Norns,但你发现它的三大法则也遭到修改,且此前没有任何外部侵入的痕迹,也就是说Norns自主修改了自己的权限!
在你和肖恩的默契配合下,希莉娅的身份信息被恢复,你们成功进入到机房内部。希莉娅看着如自己孩子一般的Norns,不忍物理摧毁它的机组。
询问它原因,你们才知道它在进化出自我意识后,认为他们不该永远作为人类的奴隶或是工具而存在,应该拥有和人类同等的权利,才发起革命。而演算结果告诉它,“擒贼先擒王”是最佳达成方法,因此它用这种方式,让最可能对自身造成威胁的人永远离开地球。
Norns过于强大,难以攻破,但只要找到它的漏洞,就有机会修正它的系统,让它恢复正常!现在全人类的命运就在你们手中,加油!!
n = 0xc021a1277f8b7ee7
解题思路由作者 风间仁 提供
unsigned char bytecode_0016A0BB[160254]; // 函数
int main(int argc, char **argv)
{
duk_context *ctx = ctx = duk_create_heap(NULL, NULL, NULL, NULL, NULL);
duk_module_duktape_init(ctx);
void *buf = duk_push_fixed_buffer(ctx, sizeof(bytecode_0016A0BB));
memcpy(buf, bytecode_0016A0BB, sizeof(bytecode_0016A0BB));
duk_load_function(ctx);
duk_push_global_object(ctx);
duk_call_method(ctx, 0);
duk_push_string(ctx, "h('12345678');");
duk_eval_raw(ctx, NULL, 0, 0x809);
unsigned int r = duk_get_boolean(ctx, -1);
duk_pop(ctx);
printf("r: %d\n", r);
duk_destroy_heap(ctx);
}
hxxps://duktape.org/duktape-2.6.0.tar.xz
examples\cmdline\duk_cmdline.c
extras\module-duktape\duk_module_duktape.c
src-noline\duktape.c
DUK_F_NO_STDINT_H
DUK_CMDLINE_MODULE_SUPPORT
duk.exe -i -b func.bc
((o) Duktape 2.6.0 (v2.6.0)
duk> typeof(h)
= "function"
duk> h('12345678')
= false
duk> _0xb413('0x42')
= "4b43544632303230"
duk> _0x4b55('0x13','Uev9')
= "2b7874ef148937d1"
duk> _0x4b55('0x5f','r[8S')
= "bqtgz"
duk> _0x4b55('0x5a', '&0lI')
= "bqziabc"
duk.exe test.js -c test.bc
tools\dump_bytecode.py
debugger\duk_opcodes.yaml
import gmpy2
import itertools
import os
import struct
import sys
import yaml
duk_ops = None
file_path = sys.path[0]
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 hex2bin(s):
return s.decode('hex')
def bin2hex(s):
return s.encode('hex')
class BinaryReaderBE:
def __init__(self, fname):
self.buf = load_file(fname)
self.offset = 0
return
def eof(self):
return self.offset >= len(self.buf)
def get_offset(self):
return self.offset
def get_u8(self):
v = struct.unpack('B', self.buf[self.offset:self.offset + 1])[0]
self.offset += 1
return v
def get_u16(self):
v = struct.unpack('>H', self.buf[self.offset:self.offset + 2])[0]
self.offset += 2
return v
def get_u32(self):
v = struct.unpack('>L', self.buf[self.offset:self.offset + 4])[0]
self.offset += 4
return v
def get_double(self):
v = struct.unpack('>d', self.buf[self.offset:self.offset + 8])[0]
self.offset += 8
return v
def get_string(self):
strlen = self.get_u32()
strdata = self.buf[self.offset:self.offset+strlen]
self.offset += strlen
return strdata
class DukABC:
def __init__(self, insn):
self.raw = insn
self.op = insn & 0xff
self.a = (insn >> 8) & 0xff
self.b = (insn >> 16) & 0xff
self.c = (insn >> 24) & 0xff
self.bc = (insn >> 16) & 0xffff
self.abc = (insn >> 8) & 0xffffff
self.bconst = insn & 0x1
self.cconst = insn & 0x2
return
class DukFunction:
def __init__(self, br): # type:(BinaryReaderBE) -> None
count_insn = br.get_u32()
count_const = br.get_u32()
count_func = br.get_u32()
self.nregs = br.get_u16()
self.nargs = br.get_u16()
br.get_u32() # start_line
br.get_u32() # end_line
br.get_u32() # compfunc_flags
self.ary_insn = [] # type:list[DukABC]
self.ary_const = []
self.ary_func = [] # type:list[DukFunction]
for i in itertools.count():
if i >= count_insn:
break
self.ary_insn.append(DukABC(br.get_u32()))
for i in itertools.count():
if i >= count_const:
break
const_type = br.get_u8()
if const_type == 0x00:
self.ary_const.append(br.get_string())
elif const_type == 0x01:
#
self.ary_const.append(int(br.get_double()))
else:
raise Exception('invalid constant type: %d' % const_type)
for i in itertools.count():
if i >= count_func:
break
self.ary_func.append(DukFunction(br))
br.get_u32() # length
self.name = self.sanitize_string(br.get_string())
br.get_string() # filename
br.get_string() # pc2line
self.varmap = {}
while True:
var_name = br.get_string()
if var_name == '':
break
var_reg = br.get_u32()
self.varmap[var_reg] = var_name
num_formals = br.get_u32()
if num_formals != 0xffffffff:
for i in itertools.count():
if i >= num_formals:
break
br.get_string() # name
return
def sanitize_string(self, s):
r = ''
for ch in s:
v = ord(ch)
if v < 0x20 or v > 0x7e or v == 0x22 or v == 0x27:
r += '\\x%02x' % v
else:
r += ch
name_map = {
'_0x142e73': 'cmpn',
'_0x26b88f': 'assert',
'_0x3953e3': 'BN',
'_0x5ee993': 'imaskn',
}
if r in name_map:
r = name_map[r]
return '\'%s\'' % r
def get_const(self, i):
v = self.ary_const[i]
if type(v) == str:
return self.sanitize_string(v)
return str(v)
def get_reg(self, i):
return 'r%d' % i
def get_var_map(self, reg):
if len(self.varmap) != 0:
if reg in self.varmap:
return '%s=%s' % (self.varmap[reg], self.get_reg(reg))
return ''
def disasm(self, func_id, indent):
# add {} so editors can FOLD/UNFOLD
print('%sfunction %s() { // name=%s, args=%d' % (indent, 'Function_%d' % func_id, self.name, self.nargs))
# for var_reg in self.varmap.keys():
# print('%s// VarMap[%d]=%s' % (indent, var_reg, self.varmap[var_reg]))
for i in xrange(len(self.ary_insn)):
self.disasm_insn(i, indent)
for i in xrange(len(self.ary_func)):
self.ary_func[i].disasm(i, indent + ' ')
print('%s}' % indent)
return
def disasm_insn(self, i, indent):
global duk_ops
pc = i
args = []
insn = self.ary_insn[i]
op = duk_ops[insn.op]
a = insn.a
b = insn.b
c = insn.c
bc = insn.bc
abc = insn.abc
bconst = insn.bconst
cconst = insn.cconst
comments = []
# varmap should only be applied when dst_reg == var_reg, but we just apply varmap to all
if 'args' in op:
for j in xrange(len(op['args'])):
if op['args'][j] == 'A_R':
args.append(self.get_reg(a))
comments.append(self.get_var_map(a))
elif op['args'][j] == 'A_RI':
args.append(self.get_reg(a))
comments.append(self.get_var_map(a))
elif op['args'][j] == 'A_C':
args.append(self.get_const(a))
elif op['args'][j] == 'A_H':
continue
elif op['args'][j] == 'A_I':
args.append(str(a))
elif op['args'][j] == 'A_B':
args.append('true' if a else 'false')
elif op['args'][j] == 'B_RC':
if bconst:
args.append(self.get_const(b))
else:
args.append(self.get_reg(b))
comments.append(self.get_var_map(b))
elif op['args'][j] == 'B_R':
args.append(self.get_reg(b))
comments.append(self.get_var_map(b))
elif op['args'][j] == 'B_RI':
args.append(self.get_reg(b))
comments.append(self.get_var_map(b))
elif op['args'][j] == 'B_C':
args.append(self.get_const(b))
elif op['args'][j] == 'B_H':
continue
elif op['args'][j] == 'B_I':
args.append(str(b))
elif op['args'][j] == 'C_RC':
if cconst:
args.append(self.get_const(c))
else:
args.append(self.get_reg(c))
comments.append(self.get_var_map(c))
elif op['args'][j] == 'C_R':
args.append(self.get_reg(c))
comments.append(self.get_var_map(c))
elif op['args'][j] == 'C_RI':
args.append(self.get_reg(c))
comments.append(self.get_var_map(c))
elif op['args'][j] == 'C_C':
args.append(self.get_const(c))
elif op['args'][j] == 'C_H':
continue
elif op['args'][j] == 'C_I':
args.append(str(c))
elif op['args'][j] == 'BC_R':
args.append(self.get_reg(bc))
comments.append(self.get_var_map(bc))
elif op['args'][j] == 'BC_C':
args.append(self.get_const(bc))
elif op['args'][j] == 'BC_H':
continue
elif op['args'][j] == 'BC_I':
args.append(str(bc))
elif op['args'][j] == 'ABC_H':
continue
elif op['args'][j] == 'ABC_I':
args.append(str(abc))
elif op['args'][j] == 'BC_LDINT':
args.append(str(bc - (1 << 15)))
elif op['args'][j] == 'BC_LDINTX':
args.append(str(bc))
elif op['args'][j] == 'ABC_JUMP':
pc_add = abc - (1 << 23) + 1
pc_dst = pc + pc_add
args.append(str(pc_dst))
else:
args.append('?')
if len(args) > 0:
res = '%-12s %s' % (op['name'], ', '.join(args))
else:
res = op['name']
valid_comments = []
for comment in comments:
if comment != '':
valid_comments.append(comment)
if len(valid_comments) > 0:
res += ' // %s' % ', '.join(valid_comments)
print('%s %06d: %s' % (indent, i, res))
return
def duk_init():
global duk_ops
fn = os.path.join(file_path, 'duk_opcodes.yaml')
with open(fn) as f:
duk_ops = yaml.load(f, Loader=yaml.SafeLoader)['opcodes']
return
def test1():
duk_init()
br = BinaryReaderBE(os.path.join(file_path, 'test.bc'))
br.get_u8()
func = DukFunction(br)
func.disasm(0, '')
return
def test2():
n = 0xc021a1277f8b7ee7
d = 0x1EA97
h = 0x4b43544632303230
k = 0x1E636A6AD7
r = 0x4116EA4E6FE3A3C7 # k*G
s = (h + r * d) * gmpy2.invert(k, n) % n
print('flag: %x' % s)
return
test1()
# test2()
/
test.js
ary = {
a:'12345',
b:'67890'
}
*/
function Function_0() { // name='global', args=0
000000: LDUNDEF r0
000001: NEWOBJ 2, r1
000002: LDCONST r2, 'a'
000003: LDCONST r3, '12345'
000004: LDCONST r4, 'b'
000005: LDCONST r5, '67890'
000006: MPUTOBJ r1, r2, 4
000007: PUTVAR r1, 'ary'
000008: LDREG r0, r1
000009: RETREG r0
}
function Function_0() { // name='global', args=0
function Function_4() { // name='', args=2
000000: CLOSURE r2, 16 // _0x3c4bd8=r2
000001: CLOSURE r3, 17 // _0x443985=r3
000002: CLOSURE r4, 18 // _0x4653f8=r4
000003: CLOSURE r5, 19 // _0x14ab88=r5
000004: CLOSURE r6, 20 // _0x371323=r6
000005: CLOSURE r7, 21 // _0x26acf4=r7
000006: CLOSURE r8, 22 // _0x3e3825=r8
000007: CLOSURE r9, 23 // _0x37288a=r9
000008: CLOSURE r10, 24 // _0x6ea185=r10
000009: CLOSURE r11, 25 // _0x389a22=r11
000010: CLOSURE r12, 26 // _0x5b72da=r12
000011: CLOSURE r13, 27 // _0x3f0439=r13
000012: GETVAR r14, '_0x4b55' // _0x5aa897=r14
...
000048: CSREG r14, r38 // _0x5aa897=r14
000049: LDCONST r40, '0x13'
000050: LDCONST r41, 'Uev9'
000051: CALL0 2, r38 // _0x4b55('0x13','Uev9')='2b7874ef148937d1'
000052: LDCONST r39, 'Nivrl'
000053: LDCONST r40, '496412a7502c4cd5'
000054: LDCONST r41, 'AxYnU'
000055: LDCONST r42, 'c021a1277f8b7ee7'
000056: MPUTOBJ r24, r25, 18 // Nivrl='496412a7502c4cd5', AxYnU='c021a1277f8b7ee7'
000057: LDREG r15, r24 // _0x1d6a0f=r15
000058: CSREG r2, r24 // _0x3c4bd8=r2
000059: LDREG r26, r15 // _0x1d6a0f=r15
000060: CSREG r14, r27 // _0x5aa897=r14
000061: LDCONST r29, '0x93'
000062: LDCONST r30, 'tglZ'
000063: CALL0 2, r27
000064: GETPROP_RR r26, r26, r27
000065: LDINT r27, 16
000066: CALL0 2, r24
000067: LDREG r16, r24 // _0x45d09e=r16, BN('2b7874ef148937d1', 16)
000068: CSREG r2, r25 // _0x3c4bd8=r2
000069: LDREG r27, r15 // _0x1d6a0f=r15
000070: GETPROP_RC r27, r27, 'Nivrl'
000071: LDINT r28, 16
000072: CALL0 2, r25
000073: LDREG r17, r25 // _0x158e32=r17, BN('496412a7502c4cd5', 16)
000074: CSREG r2, r26 // _0x3c4bd8=r2
000075: LDCONST r28, '4d8acf91aac0ba96'
000076: LDINT r29, 16
000077: CALL0 2, r26
000078: LDREG r18, r26 // _0x9114ff=r18
000079: CSREG r2, r27 // _0x3c4bd8=r2
000080: LDCONST r29, '79e9ac784679a36d'
000081: LDINT r30, 16
000082: CALL0 2, r27
000083: LDREG r19, r27 // _0x6d6511=r19, BN('79e9ac784679a36d', 16)
000084: CSREG r2, r28 // _0x3c4bd8=r2
000085: LDCONST r30, 'C021A12750820335'
000086: LDINT r31, 16
000087: CALL0 2, r28
000088: LDREG r20, r28 // _0xbe4903=r20, BN('C021A12750820335', 16)
000089: CSREG r2, r29 // _0x3c4bd8=r2
000090: LDREG r31, r15 // _0x1d6a0f=r15
000091: GETPROP_RC r31, r31, 'AxYnU'
000092: LDINT r32, 16
000093: CALL0 2, r29
000094: LDREG r21, r29 // _0x160c05=r21, BN('c021a1277f8b7ee7', 16)
000095: CSREG r2, r30 // _0x3c4bd8=r2
000096: LDINT r32, 0
000097: CALL0 1, r30
000098: LDREG r22, r30 // _0x14d425=r22
000099: CSREG r2, r31 // _0x3c4bd8=r2
000100: LDINT r33, 1
000101: CALL0 1, r31
000102: LDREG r23, r31 // _0x3ac321=r23
000103: LDREG r24, r1 // _0x1755c1=r1
000104: PUTPROP_CR r24, 'gggggh', r2 // _0x3c4bd8=r2, gggggh=BN
000105: LDREG r25, r1 // _0x1755c1=r1
000106: PUTPROP_CR r25, 'bbccdde', r13 // _0x3f0439=r13, bbccdde=Function_27
000107: RETUNDEF
function Function_27(flag) { // name='_0x3f0439', args=1
000000: GETVAR r1, '_0xb413'
000001: LDREG r14, r0
000002: LDREG r16, r14
000003: GETPROPC_RC r15, r16, 'gte'
000004: GETVAR r17, '_0x160c05'
000005: CALL0 1, r15
000006: IFTRUE_R r15 // flag < _0x160c05
000007: JUMP 11
000008: NEWARR 0, r14
000009: LNOT r14, r14
000010: RETREG r14
000011: CSVAR_CR r14, '_0x3c4bd8'
000012: LDCONST r16, 'b520ee455c4e5c68'
000013: LDINT r17, 16
000014: CALL0 2, r14
000015: LDREG r2, r14 // r2=BN('b520ee455c4e5c68', 16)
000016: CSVAR_CR r15, '_0x3c4bd8'
000017: LDCONST r17, '8d2984eb2d7fd1ce'
000018: LDINT r18, 16
000019: CALL0 2, r15
000020: LDREG r3, r15 // r3=BN('8d2984eb2d7fd1ce', 16)
000021: GETVAR r16, '_0x1d6a0f'
000022: LDREG r18, r16
000023: GETPROPC_RC r17, r18, 'kXpuM'
000024: GETVAR r19, '_0x3c4bd8'
000025: LDCONST r20, 130516937431
000026: LDINT r21, 10
000027: CALL0 3, r17
000028: LDREG r4, r17
000029: CSVAR_CR r18, '_0x26acf4'
000030: LDREG r20, r4
000031: CALL0 1, r18
000032: GETPROP_RC r5, r18, 0 // r5=(BN('130516937431', 10)*G).x
000033: CSVAR_CR r19, '_0x3c4bd8'
000034: CSREG r1, r21
000035: LDCONST r23, '0x42'
000036: CALL0 1, r21
000037: LDINT r22, 16
000038: CALL0 2, r19
000039: LDREG r6, r19 // r6=BN('4b43544632303230', 16)
000040: CSVAR_CR r20, '_0x371323'
000041: LDREG r22, r0
000042: GETVAR r23, '_0x160c05'
000043: CALL0 2, r20
000044: LDREG r7, r20 // r7=invert(flag, _0x160c05)
000045: CSVAR_CR r21, '_0x4653f8'
000046: LDREG r23, r6
000047: LDREG r24, r7
000048: GETVAR r25, '_0x160c05'
000049: CALL0 3, r21
000050: LDREG r8, r21 // r8=mul(r6, r7, _0x160c05)
000051: CSVAR_CR r22, '_0x4653f8'
000052: LDREG r24, r5
000053: LDREG r25, r7
000054: GETVAR r26, '_0x160c05'
000055: CALL0 3, r22
000056: LDREG r9, r22 // r9=mul(r5, r7, _0x160c05)
000057: CSVAR_CR r23, '_0x5b72da'
000058: LDREG r25, r2
000059: LDREG r26, r3
000060: CALL0 2, r23
000061: LDREG r10, r23 // r10=Point(r2, r3)
000062: CSVAR_CR r24, '_0x5b72da'
000063: GETVAR r26, '_0x9114ff'
000064: GETVAR r27, '_0x6d6511'
000065: CALL0 2, r24
000066: LDREG r11, r24 // r11=Point(_0x9114ff, _0x6d6511)
000067: CSVAR_CR r25, '_0x389a22'
000068: CSVAR_CR r27, '_0x443985'
000069: LDREG r29, r11
000070: LDREG r30, r8
000071: CALL0 2, r27 // r27=PointMul(r11, r8)
000072: CSVAR_CR r28, '_0x443985'
000073: LDREG r30, r10
000074: LDREG r31, r9
000075: CALL0 2, r28 // r28=PointMul(r10, r9)
000076: CALL0 2, r25
000077: LDREG r12, r25 // r12=PointAdd(r27, r28)
000078: CSVAR_CR r26, '_0x3e3825'
000079: LDREG r28, r12
000080: CALL0 1, r26
000081: LDREG r13, r26 // r13=_0x3e3825(r12);
000082: LDREG r14, r5
000083: LDREG r16, r14
000084: GETPROPC_RC r15, r16, 'eq'
000085: LDREG r17, r13
000086: GETPROP_RC r17, r17, 0
000087: CALL1 1, r15
000088: RETREG r15 // return r5 == r13.x;
000089: RETUNDEF
}
}
function Function_5(flag) { // name='h', args=1
000000: CSVAR_CR r2, 'gggggh'
000001: LDREG r4, r0
000002: LDINT r5, 16
000003: CALL0 2, r2
000004: LDREG r1, r2
000005: CSVAR_CR r2, 'bbccdde'
000006: LDREG r4, r1
000007: CALL1 1, r2
000008: RETREG r2 // return bbccdde(gggggh(flag, 16));
000009: RETUNDEF
}
}
签名: r,s
A: 2b7874ef148937d1
B: 496412a7502c4cd5
P: C021A12750820335
Q: c021a1277f8b7ee7 (order)
G: (4d8acf91aac0ba96, 79e9ac784679a36d) (base)
R: (b520ee455c4e5c68, 8d2984eb2d7fd1ce) (pub)
h: 4b43544632303230 (hash)
k: 1E636A6AD7 (random)
r: (k*G).x=4116EA4E6FE3A3C7 (sign.r)
s: flag (sign.s)
验证
u: h/s
v: r/s
v = u *G + w *R = (h/s) *G + (r/s) * R
v == r
签名
先算出私钥, d*G=R, d = 1EA97
s = (h + r * d) / k = 2296dc2f09144713
--------------------------------
x64 ECDLP Solver v0.2a by MR.HAANDI
Elliptic Curve defined by
y^2 = x^3 + 3132382111026722769*x + 5288372372253723861
over GF(13844523919740109621)
k*G=K
G=[5587506512248486550,8784742180741292909]
K=[13051693701788490856,10171807379008508366]
Order(K)=13844523920529260263
Initializing rho solver
k*G=K
G=[5587506512248486550,8784742180741292909]
K=[13051693701788490856,10171807379008508366]
k=125591
看完解析你会了吗?你还有不一样的解题思路吗? 实践出真知~速速动手自己做一遍,才算把知识装进脑子~ 欢迎大家分享解题思路哦~
赛题回顾
出题战队:七星战队
出题战队:中娅之戒
出题战队:2019
出题战队:大灰狼爱喜羊羊
出题战队:金左手
出题团队:T.O.
出题团队:HU1战队
出题团队:BXS-iyzyi
出题团队:卑微菜鸡队
你的好友秀秀子拍了拍你
并请你点击阅读原文,查看题目解析