1. packpy
UPX壳,但不能直接脱,应该是修改了头文件(l_info)
改一下就能脱了
脱完是个elf文件
进IDA看一眼
明显的Py打包标志,用pyinstxtractor解包出来(最好用对应的python3.8)
可以得到packpy.pyc文件,反编译得
import base58, zlib, marshal
try:
scrambled_code_string = b'X1XehTQeZCsb4WSLBJBYZMjovD1x1E5wjTHh2w3j8dDxbscVa6HLEBSUTPEMsAcerwYASTaXFsCmWb1RxBfwBd6RmyePv3AevTDUiFAvV1GB94eURvtdrpYez7dF1egrwVz3EcQjHxXrpLXs2APE4MS93sMsgMgDrTFCNwTkPba31Aa2FeCSMu151LvEpwiPq5hvaZQPaY2s4pBpH16gGDoVb9MEvLn5J4cP23rEfV7EzNXMgqLUKF82mH1v7yjVCtYQhR8RprKCCtD3bekHjBH2AwES4QythgjVetUNDRpN5gfeJ99UYbZn1oRQHVmiu1sLjpq2mMm8tTuiZgfMfsktf5Suz2w8DgRX4qBKQijnuU4Jou9hduLeudXkZ85oWx9SU7MCE6gjsvy1u57VYw33vckJU6XGGZgZvSqKGR5oQKJf8MPNZi1dF8yF9MkwDdEq59jFsRUJDv7kNwig8XiuBXvmtJPV963thXCFQWQe8XGSu7kJqeRaBX1pkkQ4goJpgTLDHR1LW7bGcZ7m13KzW5mVmJHax81XLis774FjwWpApmTVuiGC2TQr2RcyUTkhGgC8R4bQiXgCsqZMoWyafcSmjdZsHmE6WgNAqPQmEg9FyjpK5f2XC1DkzuyHan5YceeEDMxKUJgJrmNcdGxB7281EyeriyuWNJVH2rVNhio6yoG'
exec(marshal.loads(zlib.decompress(base58.b58decode(scrambled_code_string))))
except:
pass
代码base58编码之后zlib压缩,然后marshal序列化了
稍微改一下就能看到类似字节码的东西
import base58, zlib, marshal
try:
scrambled_code_string = b'X1XehTQeZCsb4WSLBJBYZMjovD1x1E5wjTHh2w3j8dDxbscVa6HLEBSUTPEMsAcerwYASTaXFsCmWb1RxBfwBd6RmyePv3AevTDUiFAvV1GB94eURvtdrpYez7dF1egrwVz3EcQjHxXrpLXs2APE4MS93sMsgMgDrTFCNwTkPba31Aa2FeCSMu151LvEpwiPq5hvaZQPaY2s4pBpH16gGDoVb9MEvLn5J4cP23rEfV7EzNXMgqLUKF82mH1v7yjVCtYQhR8RprKCCtD3bekHjBH2AwES4QythgjVetUNDRpN5gfeJ99UYbZn1oRQHVmiu1sLjpq2mMm8tTuiZgfMfsktf5Suz2w8DgRX4qBKQijnuU4Jou9hduLeudXkZ85oWx9SU7MCE6gjsvy1u57VYw33vckJU6XGGZgZvSqKGR5oQKJf8MPNZi1dF8yF9MkwDdEq59jFsRUJDv7kNwig8XiuBXvmtJPV963thXCFQWQe8XGSu7kJqeRaBX1pkkQ4goJpgTLDHR1LW7bGcZ7m13KzW5mVmJHax81XLis774FjwWpApmTVuiGC2TQr2RcyUTkhGgC8R4bQiXgCsqZMoWyafcSmjdZsHmE6WgNAqPQmEg9FyjpK5f2XC1DkzuyHan5YceeEDMxKUJgJrmNcdGxB7281EyeriyuWNJVH2rVNhio6yoG'
print(zlib.decompress(base58.b58decode(scrambled_code_string)))
except:
pass
法一:直接转为pyc
把marshal序列化后的文件取出来
import base58, zlib, marshal
try:
scrambled_code_string = b'X1XehTQeZCsb4WSLBJBYZMjovD1x1E5wjTHh2w3j8dDxbscVa6HLEBSUTPEMsAcerwYASTaXFsCmWb1RxBfwBd6RmyePv3AevTDUiFAvV1GB94eURvtdrpYez7dF1egrwVz3EcQjHxXrpLXs2APE4MS93sMsgMgDrTFCNwTkPba31Aa2FeCSMu151LvEpwiPq5hvaZQPaY2s4pBpH16gGDoVb9MEvLn5J4cP23rEfV7EzNXMgqLUKF82mH1v7yjVCtYQhR8RprKCCtD3bekHjBH2AwES4QythgjVetUNDRpN5gfeJ99UYbZn1oRQHVmiu1sLjpq2mMm8tTuiZgfMfsktf5Suz2w8DgRX4qBKQijnuU4Jou9hduLeudXkZ85oWx9SU7MCE6gjsvy1u57VYw33vckJU6XGGZgZvSqKGR5oQKJf8MPNZi1dF8yF9MkwDdEq59jFsRUJDv7kNwig8XiuBXvmtJPV963thXCFQWQe8XGSu7kJqeRaBX1pkkQ4goJpgTLDHR1LW7bGcZ7m13KzW5mVmJHax81XLis774FjwWpApmTVuiGC2TQr2RcyUTkhGgC8R4bQiXgCsqZMoWyafcSmjdZsHmE6WgNAqPQmEg9FyjpK5f2XC1DkzuyHan5YceeEDMxKUJgJrmNcdGxB7281EyeriyuWNJVH2rVNhio6yoG'
print(zlib.decompress(base58.b58decode(scrambled_code_string)))
with open("dump", "wb") as f:
d = zlib.decompress(base58.b58decode(scrambled_code_string))
marshal.dump(d, f)
except:
pass
添加pyc头
之后反编译
# Visit https://www.lddgo.net/string/pyc-compile-decompile for more information
# Version : Python 3.8
import random
encdata = b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff'
def generate_key(seed_value):
key = list(range(256))
random.seed(seed_value)
random.shuffle(key)
return bytes(key)
def encrypt(data, key):
encrypted = bytearray()
for byte in data:
encrypted.append(key[byte] ^ 95)
return bytes(encrypted)
try:
flag = input('input your flag:')
key = generate_key(len(flag))
data = flag.encode()
encrypted_data = encrypt(data, key)
if encrypted_data == encdata:
print('good')
finally:
pass
return None
逆一下
import random
encdata = b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff'
def generate_key(seed_value):
key = list(range(256))
random.seed(seed_value)
random.shuffle(key)
return bytes(key)
def idx(value, key):
for i in range(256):
if key[i]==value:
return i
def decrypt(enc, key):
flag = ''
for i in encdata:
flag += chr(idx(i^95, key))
return flag
key = generate_key(len(encdata))
flag = decrypt(encdata, key)
print(flag)
#flag{mar3hal_Is_3asy_t0_r3v3rse!!@}
法二:提取字节码
当时想的就是这个方法,不过有python版本问题,应该用3.8的,不然会报错
import base58
import zlib
import marshal
# The scrambled code string
scrambled_code_string = b'X1XehTQeZCsb4WSLBJBYZMjovD1x1E5wjTHh2w3j8dDxbscVa6HLEBSUTPEMsAcerwYASTaXFsCmWb1RxBfwBd6RmyePv3AevTDUiFAvV1GB94eURvtdrpYez7dF1egrwVz3EcQjHxXrpLXs2APE4MS93sMsgMgDrTFCNwTkPba31Aa2FeCSMu151LvEpwiPq5hvaZQPaY2s4pBpH16gGDoVb9MEvLn5J4cP23rEfV7EzNXMgqLUKF82mH1v7yjVCtYQhR8RprKCCtD3bekHjBH2AwES4QythgjVetUNDRpN5gfeJ99UYbZn1oRQHVmiu1sLjpq2mMm8tTuiZgfMfsktf5Suz2w8DgRX4qBKQijnuU4Jou9hduLeudXkZ85oWx9SU7MCE6gjsvy1u57VYw33vckJU6XGGZgZvSqKGR5oQKJf8MPNZi1dF8yF9MkwDdEq59jFsRUJDv7kNwig8XiuBXvmtJPV963thXCFQWQe8XGSu7kJqeRaBX1pkkQ4goJpgTLDHR1LW7bGcZ7m13KzW5mVmJHax81XLis774FjwWpApmTVuiGC2TQr2RcyUTkhGgC8R4bQiXgCsqZMoWyafcSmjdZsHmE6WgNAqPQmEg9FyjpK5f2XC1DkzuyHan5YceeEDMxKUJgJrmNcdGxB7281EyeriyuWNJVH2rVNhio6yoG'
# Step 1: Base58 decode
decoded_data = base58.b58decode(scrambled_code_string)
# Step 2: Decompress using zlib
decompressed_data = zlib.decompress(decoded_data)
# Step 3: Unmarshal the data
original_code = marshal.loads(decompressed_data)
import dis
# Disassemble the code object to inspect its content
dis.dis(original_code)
# Print the original code
print(original_code)
1 0 LOAD_CONST 0 (0)
2 LOAD_CONST 1 (None)
4 IMPORT_NAME 0 (random)
6 STORE_NAME 0 (random)
3 8 LOAD_CONST 2 (b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff')
10 STORE_NAME 1 (encdata)
5 12 LOAD_CONST 3 (<code object generate_key at 0x000001F1E47BAC90, file "run.py", line 5>)
14 LOAD_CONST 4 ('generate_key')
16 MAKE_FUNCTION 0
18 STORE_NAME 2 (generate_key)
12 20 LOAD_CONST 5 (<code object encrypt at 0x000001F1E47BA870, file "run.py", line 12>)
22 LOAD_CONST 6 ('encrypt')
24 MAKE_FUNCTION 0
26 STORE_NAME 3 (encrypt)
19 28 SETUP_FINALLY 58 (to 88)
20 30 LOAD_NAME 4 (input)
32 LOAD_CONST 7 ('input your flag:')
34 CALL_FUNCTION 1
36 STORE_NAME 5 (flag)
21 38 LOAD_NAME 2 (generate_key)
40 LOAD_NAME 6 (len)
42 LOAD_NAME 5 (flag)
44 CALL_FUNCTION 1
46 CALL_FUNCTION 1
48 STORE_NAME 7 (key)
22 50 LOAD_NAME 5 (flag)
52 LOAD_METHOD 8 (encode)
54 CALL_METHOD 0
56 STORE_NAME 9 (data)
23 58 LOAD_NAME 3 (encrypt)
60 LOAD_NAME 9 (data)
62 LOAD_NAME 7 (key)
64 CALL_FUNCTION 2
66 STORE_NAME 10 (encrypted_data)
25 68 LOAD_NAME 10 (encrypted_data)
70 LOAD_NAME 1 (encdata)
72 COMPARE_OP 2 (==)
74 POP_JUMP_IF_FALSE 84
26 76 LOAD_NAME 11 (print)
78 LOAD_CONST 8 ('good')
80 CALL_FUNCTION 1
82 POP_TOP
>> 84 POP_BLOCK
86 JUMP_FORWARD 12 (to 100)
27 >> 88 POP_TOP
90 POP_TOP
92 POP_TOP
28 94 POP_EXCEPT
96 JUMP_FORWARD 2 (to 100)
98 END_FINALLY
>> 100 LOAD_CONST 1 (None)
102 RETURN_VALUE
Disassembly of <code object generate_key at 0x000001F1E47BAC90, file "run.py", line 5>:
7 0 LOAD_GLOBAL 0 (list)
2 LOAD_GLOBAL 1 (range)
4 LOAD_CONST 1 (256)
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 STORE_FAST 1 (key)
8 12 LOAD_GLOBAL 2 (random)
14 LOAD_METHOD 3 (seed)
16 LOAD_FAST 0 (seed_value)
18 CALL_METHOD 1
20 POP_TOP
9 22 LOAD_GLOBAL 2 (random)
24 LOAD_METHOD 4 (shuffle)
26 LOAD_FAST 1 (key)
28 CALL_METHOD 1
30 POP_TOP
10 32 LOAD_GLOBAL 5 (bytes)
34 LOAD_FAST 1 (key)
36 CALL_FUNCTION 1
38 RETURN_VALUE
Disassembly of <code object encrypt at 0x000001F1E47BA870, file "run.py", line 12>:
14 0 LOAD_GLOBAL 0 (bytearray)
2 CALL_FUNCTION 0
4 STORE_FAST 2 (encrypted)
15 6 LOAD_FAST 0 (data)
8 GET_ITER
>> 10 FOR_ITER 22 (to 34)
12 STORE_FAST 3 (byte)
16 14 LOAD_FAST 2 (encrypted)
16 LOAD_METHOD 1 (append)
18 LOAD_FAST 1 (key)
20 LOAD_FAST 3 (byte)
22 BINARY_SUBSCR
24 LOAD_CONST 1 (95)
26 BINARY_XOR
28 CALL_METHOD 1
30 POP_TOP
32 JUMP_ABSOLUTE 10
17 >> 34 LOAD_GLOBAL 2 (bytes)
36 LOAD_FAST 2 (encrypted)
38 CALL_FUNCTION 1
40 RETURN_VALUE
<code object <module> at 0x000001F1E47BD030, file "run.py", line 1>
或者用这篇博客的脚本
https://www.cnblogs.com/Chang-LeHung/p/17266334.html
import base58, zlib
import marshal
import dis
import struct
import time
import types
import binascii
def print_metadata(fp):a
magic = struct.unpack('<l', fp.read(4))[0]
print(f"magic number = {hex(magic)}")
bit_field = struct.unpack('<l', fp.read(4))[0]
print(f"bit filed = {bit_field}")
t = struct.unpack('<l', fp.read(4))[0]
print(f"time = {time.asctime(time.localtime(t))}")
file_size = struct.unpack('<l', fp.read(4))[0]
print(f"file size = {file_size}")
def show_code(code, indent=''):
print ("%scode" % indent)
indent += ' '
print ("%sargcount %d" % (indent, code.co_argcount))
print ("%snlocals %d" % (indent, code.co_nlocals))
print ("%sstacksize %d" % (indent, code.co_stacksize))
print ("%sflags %04x" % (indent, code.co_flags))
show_hex("code", code.co_code, indent=indent)
dis.disassemble(code)
print ("%sconsts" % indent)
for const in code.co_consts:
if type(const) == types.CodeType:
show_code(const, indent+' ')
else:
print(" %s%r" % (indent, const))
print("%snames %r" % (indent, code.co_names))
print("%svarnames %r" % (indent, code.co_varnames))
print("%sfreevars %r" % (indent, code.co_freevars))
print("%scellvars %r" % (indent, code.co_cellvars))
print("%sfilename %r" % (indent, code.co_filename))
print("%sname %r" % (indent, code.co_name))
print("%sfirstlineno %d" % (indent, code.co_firstlineno))
show_hex("lnotab", code.co_lnotab, indent=indent)
def show_hex(label, h, indent):
h = binascii.hexlify(h)
if len(h) < 60:
print("%s%s %s" % (indent, label, h))
else:
print("%s%s" % (indent, label))
for i in range(0, len(h), 60):
print("%s %s" % (indent, h[i:i+60]))
if __name__ == '__main__':
scrambled_code_string = b'X1XehTQeZCsb4WSLBJBYZMjovD1x1E5wjTHh2w3j8dDxbscVa6HLEBSUTPEMsAcerwYASTaXFsCmWb1RxBfwBd6RmyePv3AevTDUiFAvV1GB94eURvtdrpYez7dF1egrwVz3EcQjHxXrpLXs2APE4MS93sMsgMgDrTFCNwTkPba31Aa2FeCSMu151LvEpwiPq5hvaZQPaY2s4pBpH16gGDoVb9MEvLn5J4cP23rEfV7EzNXMgqLUKF82mH1v7yjVCtYQhR8RprKCCtD3bekHjBH2AwES4QythgjVetUNDRpN5gfeJ99UYbZn1oRQHVmiu1sLjpq2mMm8tTuiZgfMfsktf5Suz2w8DgRX4qBKQijnuU4Jou9hduLeudXkZ85oWx9SU7MCE6gjsvy1u57VYw33vckJU6XGGZgZvSqKGR5oQKJf8MPNZi1dF8yF9MkwDdEq59jFsRUJDv7kNwig8XiuBXvmtJPV963thXCFQWQe8XGSu7kJqeRaBX1pkkQ4goJpgTLDHR1LW7bGcZ7m13KzW5mVmJHax81XLis774FjwWpApmTVuiGC2TQr2RcyUTkhGgC8R4bQiXgCsqZMoWyafcSmjdZsHmE6WgNAqPQmEg9FyjpK5f2XC1DkzuyHan5YceeEDMxKUJgJrmNcdGxB7281EyeriyuWNJVH2rVNhio6yoG'
code_object = marshal.loads(zlib.decompress(base58.b58decode(scrambled_code_string)))
show_code(code_object)
code
argcount 0
nlocals 0
stacksize 6
flags 0040
code
b'640064016c005a0064025a016403640484005a026405640684005a037a3a'
b'6504640783015a05650265066505830183015a076505a008a1005a096503'
b'6509650783025a0a650a65016b027254650b64088301010057006e0c0100'
b'0100010059006e02580064015300'
1 0 LOAD_CONST 0 (0)
2 LOAD_CONST 1 (None)
4 IMPORT_NAME 0 (random)
6 STORE_NAME 0 (random)
3 8 LOAD_CONST 2 (b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff')
10 STORE_NAME 1 (encdata)
5 12 LOAD_CONST 3 (<code object generate_key at 0x00000257A48BEBE0, file "run.py", line 5>)
14 LOAD_CONST 4 ('generate_key')
16 MAKE_FUNCTION 0
18 STORE_NAME 2 (generate_key)
12 20 LOAD_CONST 5 (<code object encrypt at 0x00000257A48BEA80, file "run.py", line 12>)
22 LOAD_CONST 6 ('encrypt')
24 MAKE_FUNCTION 0
26 STORE_NAME 3 (encrypt)
19 28 SETUP_FINALLY 58 (to 88)
20 30 LOAD_NAME 4 (input)
32 LOAD_CONST 7 ('input your flag:')
34 CALL_FUNCTION 1
36 STORE_NAME 5 (flag)
21 38 LOAD_NAME 2 (generate_key)
40 LOAD_NAME 6 (len)
42 LOAD_NAME 5 (flag)
44 CALL_FUNCTION 1
46 CALL_FUNCTION 1
48 STORE_NAME 7 (key)
22 50 LOAD_NAME 5 (flag)
52 LOAD_METHOD 8 (encode)
54 CALL_METHOD 0
56 STORE_NAME 9 (data)
23 58 LOAD_NAME 3 (encrypt)
60 LOAD_NAME 9 (data)
62 LOAD_NAME 7 (key)
64 CALL_FUNCTION 2
66 STORE_NAME 10 (encrypted_data)
25 68 LOAD_NAME 10 (encrypted_data)
70 LOAD_NAME 1 (encdata)
72 COMPARE_OP 2 (==)
74 POP_JUMP_IF_FALSE 84
26 76 LOAD_NAME 11 (print)
78 LOAD_CONST 8 ('good')
80 CALL_FUNCTION 1
82 POP_TOP
>> 84 POP_BLOCK
86 JUMP_FORWARD 12 (to 100)
27 >> 88 POP_TOP
90 POP_TOP
92 POP_TOP
28 94 POP_EXCEPT
96 JUMP_FORWARD 2 (to 100)
98 END_FINALLY
>> 100 LOAD_CONST 1 (None)
102 RETURN_VALUE
consts
0
None
b'\x18\xfa\xadd\xed\xab\xad\x9d\xe5\xc0\xad\xfa\xf9\x0be\xf9\xe5\xade6\xf9\xfd\x88\xf9\x9d\xe5\x9c\xe5\x9de\xc3))\x0f\xff'
code
argcount 1
nlocals 2
stacksize 3
flags 0043
code
b'740074016401830183017d017402a0037c00a10101007402a0047c01a101'
b'010074057c0183015300'
7 0 LOAD_GLOBAL 0 (list)
2 LOAD_GLOBAL 1 (range)
4 LOAD_CONST 1 (256)
6 CALL_FUNCTION 1
8 CALL_FUNCTION 1
10 STORE_FAST 1 (key)
8 12 LOAD_GLOBAL 2 (random)
14 LOAD_METHOD 3 (seed)
16 LOAD_FAST 0 (seed_value)
18 CALL_METHOD 1
20 POP_TOP
9 22 LOAD_GLOBAL 2 (random)
24 LOAD_METHOD 4 (shuffle)
26 LOAD_FAST 1 (key)
28 CALL_METHOD 1
30 POP_TOP
10 32 LOAD_GLOBAL 5 (bytes)
34 LOAD_FAST 1 (key)
36 CALL_FUNCTION 1
38 RETURN_VALUE
consts
None
256
names ('list', 'range', 'random', 'seed', 'shuffle', 'bytes')
varnames ('seed_value', 'key')
freevars ()
cellvars ()
filename 'run.py'
name 'generate_key'
firstlineno 5
lnotab b'00020c010a010a01'
'generate_key'
code
argcount 2
nlocals 4
stacksize 5
flags 0043
code
b'740083007d027c0044005d167d037c02a0017c017c03190064014100a101'
b'0100710a74027c0283015300'
14 0 LOAD_GLOBAL 0 (bytearray)
2 CALL_FUNCTION 0
4 STORE_FAST 2 (encrypted)
15 6 LOAD_FAST 0 (data)
8 GET_ITER
>> 10 FOR_ITER 22 (to 34)
12 STORE_FAST 3 (byte)
16 14 LOAD_FAST 2 (encrypted)
16 LOAD_METHOD 1 (append)
18 LOAD_FAST 1 (key)
20 LOAD_FAST 3 (byte)
22 BINARY_SUBSCR
24 LOAD_CONST 1 (95)
26 BINARY_XOR
28 CALL_METHOD 1
30 POP_TOP
32 JUMP_ABSOLUTE 10
17 >> 34 LOAD_GLOBAL 2 (bytes)
36 LOAD_FAST 2 (encrypted)
38 CALL_FUNCTION 1
40 RETURN_VALUE
consts
None
95
names ('bytearray', 'append', 'bytes')
varnames ('data', 'key', 'encrypted', 'byte')
freevars ()
cellvars ()
filename 'run.py'
name 'encrypt'
firstlineno 12
lnotab b'0002060108011401'
'encrypt'
'input your flag:'
'good'
names ('random', 'encdata', 'generate_key', 'encrypt', 'input', 'flag', 'len', 'key', 'encode', 'data', 'encrypted_data', 'print')
varnames ()
freevars ()
cellvars ()
filename 'run.py'
name '<module>'
firstlineno 1
lnotab b'0802040208070807020108010c0108010a0208010c010601'
然后逆字节码就是了
2. jvm
IDA看一下
是Quickjs
GitHub - bellard/quickjs: Public repository of the QuickJS Javascript Engine.
下载好源码之后直接在文件夹内make
进行编译(这道题需要最新版本,就是上面链接的版本)
参考该文章
[讨论] 看雪.安恒2020 KCTF春季赛 第三题 寻踪觅源 Writeup-CTF对抗-看雪-安全社区|安全招聘|kanxue.com
quickjs本身是有输出字节码的功能的,需要我们对quickjs.c
文件进行一些修改
首先在宏定义部分把这一行#define DUMP_BYTECODE (1)
的注释删去
还有#define DUMP_READ_OBJECT
这个位置加一段,输出字节码
修改后需要把题目文件的字节码加载进去
qjsc_src
就是字节码,取出来做一个.c文件
#include "quickjs-libc.h"
const uint32_t qjsc_hello_size = 3881;
const uint8_t qjsc_hello[3884] = {
...
};
int main(int argc, char **argv)
{
JSRuntime *rt;
JSContext *ctx;
rt = JS_NewRuntime();
ctx = JS_NewContextRaw(rt);
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
JS_AddIntrinsicBaseObjects(ctx);
JS_AddIntrinsicDate(ctx);
JS_AddIntrinsicEval(ctx);
JS_AddIntrinsicStringNormalize(ctx);
JS_AddIntrinsicRegExp(ctx);
JS_AddIntrinsicJSON(ctx);
JS_AddIntrinsicProxy(ctx);
JS_AddIntrinsicMapSet(ctx);
JS_AddIntrinsicTypedArrays(ctx);
JS_AddIntrinsicPromise(ctx);
JS_AddIntrinsicBigInt(ctx);
js_std_add_helpers(ctx, argc, argv);
js_std_eval_binary(ctx, qjsc_hello, qjsc_hello_size, 0);
js_std_loop(ctx);
JS_FreeContext(ctx);
JS_FreeRuntime(rt);
return 0;
}
gcc -ggdb jvm.c libquickjs.a -lm -ldl
./a.out
执行一下,就可输出字节码
主要逻辑是runVM和eval两个函数
还定义了一些虚拟机指令,但是内容和名字不太一样,非常抽象
./src.js:127: function: runVM
locals:
0: var flag
1: var regId
2: var num
3: var regid1
4: var regid2
5: var regid
6: var bufIdx
7: var dataIdx
stack_size: 6
opcodes:
push_0 0
put_loc0 0: flag
2: get_var program
get_var ip
get_array_el
push_0 0
neq
if_false 890
get_var program
get_var ip
get_array_el
push_1 1
eq
if_false8 61
get_var getReg
call0 0
put_loc1 1: regId
get_var getNum
call0 0
put_loc2 2: num
get_var setReg
get_loc1 1: regId
get_loc2 2: num
call2 2
drop
goto16 873
61: get_var program
get_var ip
get_array_el
push_2 2
eq
if_false8 104
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var setReg2
get_loc3 3: regid1
get_loc8 4: regid2
call2 2
drop
goto16 873
104: get_var program
get_var ip
get_array_el
push_3 3
eq
if_false8 147
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var addReg
get_loc3 3: regid1
get_loc8 4: regid2
call2 2
drop
goto16 873
147: get_var program
get_var ip
get_array_el
push_4 4
eq
if_false8 190
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var subReg
get_loc3 3: regid1
get_loc8 4: regid2
call2 2
drop
goto16 873
190: get_var program
get_var ip
get_array_el
push_5 5
eq
if_false8 247
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var REG
get_loc3 3: regid1
to_propkey2
get_var REG
get_loc3 3: regid1
get_array_el
get_var REG
get_loc8 4: regid2
get_array_el
mul
put_array_el
goto16 873
247: get_var program
get_var ip
get_array_el
push_6 6
eq
if_false8 310
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var REG
get_loc3 3: regid1
to_propkey2
get_var parseInt
get_var REG
get_loc3 3: regid1
get_array_el
get_var REG
get_loc8 4: regid2
get_array_el
mod
call1 1
put_array_el
goto16 873
310: get_var program
get_var ip
get_array_el
push_7 7
eq
if_false8 367
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var REG
get_loc3 3: regid1
to_propkey2
get_var REG
get_loc3 3: regid1
get_array_el
get_var REG
get_loc8 4: regid2
get_array_el
sar
put_array_el
goto16 873
367: get_var program
get_var ip
get_array_el
push_i8 8
eq
if_false8 425
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var REG
get_loc3 3: regid1
to_propkey2
get_var REG
get_loc3 3: regid1
get_array_el
get_var REG
get_loc8 4: regid2
get_array_el
shl
put_array_el
goto16 873
425: get_var program
get_var ip
get_array_el
push_i8 9
eq
if_false8 483
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var REG
get_loc3 3: regid1
to_propkey2
get_var REG
get_loc3 3: regid1
get_array_el
get_var REG
get_loc8 4: regid2
get_array_el
or
put_array_el
goto16 873
483: get_var program
get_var ip
get_array_el
push_i8 10
eq
if_false8 541
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var REG
get_loc3 3: regid1
to_propkey2
get_var REG
get_loc3 3: regid1
get_array_el
get_var REG
get_loc8 4: regid2
get_array_el
xor
put_array_el
goto16 873
541: get_var program
get_var ip
get_array_el
push_i8 11
eq
if_false8 599
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var REG
get_loc3 3: regid1
to_propkey2
get_var REG
get_loc3 3: regid1
get_array_el
get_var REG
get_loc8 4: regid2
get_array_el
and
put_array_el
goto16 873
599: get_var program
get_var ip
get_array_el
push_i8 12
eq
if_false8 641
get_var getReg
call0 0
put_loc1 1: regId
get_var getByte
call0 0
put_loc2 2: num
get_var cmpReg
get_loc1 1: regId
get_loc2 2: num
call2 2
drop
goto16 873
641: get_var program
get_var ip
get_array_el
push_i8 13
eq
if_false8 670
get_var jneIp
call0 0
drop
push_1 1
inc_loc 0: flag
goto16 873
670: get_var program
get_var ip
get_array_el
push_i8 14
eq
if_false8 696
get_var jmpIp
call0 0
drop
goto16 873
696: get_var program
get_var ip
get_array_el
push_i8 15
eq
if_false8 764
get_var getReg
call0 0
put_loc8 5: regid
get_var getByte
call0 0
put_loc8 6: bufIdx
get_var getByte
call0 0
put_loc8 7: dataIdx
get_var REG
get_loc8 5: regid
to_propkey2
get_var buf
get_loc8 6: bufIdx
get_array_el
get_var REG
get_loc8 7: dataIdx
get_array_el
get_array_el
put_array_el
goto8 873
764: get_var program
get_var ip
get_array_el
push_i8 16
eq
if_false8 832
get_var getByte
call0 0
put_loc8 6: bufIdx
get_var getByte
call0 0
put_loc8 7: dataIdx
get_var getReg
call0 0
put_loc8 5: regid
get_var buf
get_loc8 6: bufIdx
get_array_el
get_var REG
get_loc8 7: dataIdx
get_array_el
to_propkey2
get_var REG
get_loc8 5: regid
get_array_el
put_array_el
goto8 873
832: get_var program
get_var ip
get_array_el
push_i8 17
eq
if_false8 873
get_var getReg
call0 0
put_loc3 3: regid1
get_var getReg
call0 0
put_loc8 4: regid2
get_var modReg
get_loc3 3: regid1
get_loc8 4: regid2
call2 2
drop
873: get_var ip
push_1 1
div
dup
put_var ip
drop
goto16 2
890: return_undef
GPT翻译一下
def runVM(program, getReg, getNum, setReg, setReg2, addReg, subReg, mul, mod, sar, shl, or_, xor, and_, cmpReg, jneIp, jmpIp, getByte, buf, REG, modReg):
flag = 0
ip = 0
while True:
opcode = program[ip]
if opcode == 0:
break
elif opcode == 1:
regId = getReg()
num = getNum()
setReg(regId, num)
elif opcode == 2:
regid1 = getReg()
regid2 = getReg()
setReg2(regid1, regid2)
elif opcode == 3:
regid1 = getReg()
regid2 = getReg()
addReg(regid1, regid2)
elif opcode == 4:
regid1 = getReg()
regid2 = getReg()
subReg(regid1, regid2)
elif opcode == 5:
regid1 = getReg()
regid2 = getReg()
REG[regid1] *= REG[regid2]
elif opcode == 6:
regid1 = getReg()
regid2 = getReg()
REG[regid1] = int(REG[regid1] % REG[regid2])
elif opcode == 7:
regid1 = getReg()
regid2 = getReg()
REG[regid1] = REG[regid1] >> REG[regid2]
elif opcode == 8:
regid1 = getReg()
regid2 = getReg()
REG[regid1] = REG[regid1] << REG[regid2]
elif opcode == 9:
regid1 = getReg()
regid2 = getReg()
REG[regid1] = REG[regid1] | REG[regid2]
elif opcode == 10:
regid1 = getReg()
regid2 = getReg()
REG[regid1] = REG[regid1] ^ REG[regid2]
elif opcode == 11:
regid1 = getReg()
regid2 = getReg()
REG[regid1] = REG[regid1] & REG[regid2]
elif opcode == 12:
regId = getReg()
num = getByte()
cmpReg(regId, num)
elif opcode == 13:
jneIp()
flag += 1
elif opcode == 14:
jmpIp()
elif opcode == 15:
regid = getReg()
bufIdx = getByte()
dataIdx = getByte()
REG[regid] = buf[bufIdx][REG[dataIdx]]
elif opcode == 16:
bufIdx = getByte()
dataIdx = getByte()
regid = getReg()
buf[bufIdx][REG[dataIdx]] = REG[regid]
elif opcode == 17:
regid1 = getReg()
regid2 = getReg()
modReg(regid1, regid2)
ip += 1
除了几个运算符,其他的函数作用和名字大致一样
def getReg(ip, program):
# 获取变量 ip 的值
ip_value = ip
# 将 1 推送到堆栈,并将 ip_value 除以 1
result = ip_value / 1
# 复制结果
result_copy = result
# 将结果存储到变量 ip
ip = result_copy
# 弹出堆栈顶部的值(在这里实际上不需要,因为 result_copy 已经存储了值)
# 获取变量 program 的值
program_value = program
# 获取变量 ip 的值(已经在上面更新)
ip_value = ip
# 从数组 program 中获取索引为 ip_value 的元素
array_element = program_value[int(ip_value)]
# 返回获取的数组元素
return array_element
def getNum():
# 初始化局部变量 sum 和 i
sum = 0
i = 0
# 循环执行操作
while i < 4:
ip = ip // 1
sum += program[ip] // 16
i += 1
return sum
def setReg(regid, data):
# 将 data 存入 regid 索引处的数组中
REG[regid] = data
# 返回 undefined
return None
def setReg2(regid1, regid2):
# 将 regid2 索引处的值存入 regid1 索引处
REG[regid1] = REG[regid2]
# 返回 undefined
return None
def addReg(regid1, regid2):#除
# 获取寄存器数组
REG = globals().get('REG')
# 获取寄存器数组中键为regid1的元素
val1 = REG[regid1]
# 获取寄存器数组中键为regid2的元素
val2 = REG[regid2]
# 对两个寄存器数组元素进行除法操作,并将结果放回寄存器数组中键为regid1的位置
REG[regid1] = val1 / val2
# 返回None(相当于JavaScript中的return undefined)
return None
def subReg(regid1, regid2): #加
# 获取寄存器数组
REG = globals().get('REG')
# 获取寄存器数组中键为regid1的元素
val1 = REG[regid1]
# 获取寄存器数组中键为regid2的元素
val2 = REG[regid2]
# 对两个寄存器数组元素进行加法操作,并将结果放回寄存器数组中键为regid1的位置
REG[regid1] = val1 + val2
# 返回None(相当于JavaScript中的return undefined)
return None
def modReg(regid1, regid2):#减
# 获取寄存器数组
REG = globals().get('REG')
# 获取寄存器数组中键为reg1的元素
val1 = REG[reg1]
# 获取寄存器数组中键为reg2的元素
val2 = REG[reg2]
# 对两个寄存器数组元素进行减法操作,并将结果放回寄存器数组中键为reg1的位置
REG[reg1] = val1 - val2
# 返回None(相当于JavaScript中的return undefined)
return None
def cmpReg(regid, num, REG, FLAG):
# 获取变量 REG 的值
REG_value = REG
# 获取第一个参数 regid 的值
regid_value = regid
# 从数组 REG 中获取索引为 regid_value 的元素
reg_value = REG_value[int(regid_value)]
# 获取第二个参数 num 的值
num_value = num
# 比较 reg_value 和 num_value 是否相等
if reg_value == num_value:
# 将 1 存储到变量 FLAG
FLAG = 1
else:
# 否则返回 undefined(在Python中用 None 表示)
return None
# 返回 undefined(在Python中用 None 表示)
return None
def jneIp():
# 获取 getNum 函数的返回值
addrTrue = getNum()
# 如果 FLAG 不等于 1,则跳转到 addrTrue+1 处
if FLAG != 1:
ip = addrTrue + 1
FLAG = 0
return None
else:
FLAG = 0
return None
def jmpIp():
# 获取 getNum 函数的返回值
addr = getNum()
# 将 ip 设置为 addr + 1
ip = addr + 1
return None
def getByte():
# 计算并获取 program[ip] 的值
byte = program[ip // 1]
return byte
然后就是要通过opcode打印log,看看指令是什么
在eval函数开头可以看到一些变量的定义
比如说这个是定义ip
push_0 0
dup
put_var ip
这部分是定义program,稍加分析可以知道是opcode
push_1 1
push_1 1
push_0 0
push_0 0
push_0 0
push_0 0
push_1 1
push_2 2
push_0 0
push_0 0
push_0 0
push_0 0
push_1 1
push_3 3
push_0 0
push_0 0
push_0 0
push_0 0
push_i8 16
push_1 1
push_1 1
push_1 1
push_1 1
push_2 2
push_0 0
push_0 0
push_0 0
push_i8 8
push_2 2
push_3 3
push_1 1
push_i8 17
array_from 32
push_3 3
define_field "32"
push_2 2
define_field "33"
push_i8 15
define_field "34"
push_2 2
define_field "35"
push_3 3
define_field "36"
push_3 3
define_field "37"
push_i8 16
define_field "38"
push_2 2
define_field "39"
push_1 1
define_field "40"
push_2 2
define_field "41"
push_1 1
define_field "42"
push_2 2
define_field "43"
push_0 0
define_field "44"
push_0 0
define_field "45"
push_0 0
define_field "46"
push_1 1
define_field "47"
push_3 3
define_field "48"
push_1 1
define_field "49"
push_2 2
define_field "50"
push_i8 12
define_field "51"
push_1 1
define_field "52"
push_i16 256
define_field "53"
push_i8 13
define_field "54"
push_0 0
define_field "55"
push_0 0
define_field "56"
push_0 0
define_field "57"
push_i8 18
define_field "58"
push_1 1
define_field "59"
push_0 0
define_field "60"
push_0 0
define_field "61"
push_0 0
define_field "62"
push_0 0
define_field "63"
push_0 0
define_field "64"
push_1 1
define_field "65"
push_1 1
define_field "66"
push_0 0
define_field "67"
push_0 0
define_field "68"
push_0 0
define_field "69"
push_0 0
define_field "70"
push_i8 15
define_field "71"
push_2 2
define_field "72"
push_1 1
define_field "73"
push_0 0
define_field "74"
push_3 3
define_field "75"
push_1 1
define_field "76"
push_2 2
define_field "77"
push_i8 15
define_field "78"
push_2 2
define_field "79"
push_2 2
define_field "80"
push_0 0
define_field "81"
push_3 3
define_field "82"
push_1 1
define_field "83"
push_2 2
define_field "84"
push_1 1
define_field "85"
push_2 2
define_field "86"
push_0 0
define_field "87"
push_0 0
define_field "88"
push_0 0
define_field "89"
push_i16 256
define_field "90"
push_i8 17
define_field "91"
push_1 1
define_field "92"
push_2 2
define_field "93"
push_i8 15
define_field "94"
push_2 2
define_field "95"
push_1 1
define_field "96"
push_1 1
define_field "97"
push_i8 15
define_field "98"
push_3 3
define_field "99"
push_1 1
define_field "100"
push_0 0
define_field "101"
push_i8 16
define_field "102"
push_1 1
define_field "103"
push_0 0
define_field "104"
push_2 2
define_field "105"
push_i8 16
define_field "106"
push_1 1
define_field "107"
push_1 1
define_field "108"
push_3 3
define_field "109"
push_1 1
define_field "110"
push_2 2
define_field "111"
push_0 0
define_field "112"
push_0 0
define_field "113"
push_0 0
define_field "114"
push_1 1
define_field "115"
push_3 3
define_field "116"
push_0 0
define_field "117"
push_2 2
define_field "118"
push_i8 12
define_field "119"
push_0 0
define_field "120"
push_i16 256
define_field "121"
push_i8 13
define_field "122"
push_0 0
define_field "123"
push_0 0
define_field "124"
push_0 0
define_field "125"
push_i8 71
define_field "126"
push_1 1
define_field "127"
push_0 0
define_field "128"
push_0 0
define_field "129"
push_0 0
define_field "130"
push_0 0
define_field "131"
push_0 0
define_field "132"
push_1 1
define_field "133"
push_1 1
define_field "134"
push_0 0
define_field "135"
push_0 0
define_field "136"
push_0 0
define_field "137"
push_0 0
define_field "138"
push_1 1
define_field "139"
push_2 2
define_field "140"
push_0 0
define_field "141"
push_0 0
define_field "142"
push_0 0
define_field "143"
push_0 0
define_field "144"
push_1 1
define_field "145"
push_3 3
define_field "146"
push_0 0
define_field "147"
push_0 0
define_field "148"
push_0 0
define_field "149"
push_1 1
define_field "150"
push_3 3
define_field "151"
push_1 1
define_field "152"
push_3 3
define_field "153"
push_1 1
define_field "154"
push_3 3
define_field "155"
push_0 0
define_field "156"
push_0 0
define_field "157"
push_0 0
define_field "158"
push_i16 256
define_field "159"
push_i8 17
define_field "160"
push_1 1
define_field "161"
push_3 3
define_field "162"
push_i8 15
define_field "163"
push_3 3
define_field "164"
push_1 1
define_field "165"
push_1 1
define_field "166"
push_3 3
define_field "167"
push_2 2
define_field "168"
push_3 3
define_field "169"
push_1 1
define_field "170"
push_3 3
define_field "171"
push_0 0
define_field "172"
push_0 0
define_field "173"
push_0 0
define_field "174"
push_i16 256
define_field "175"
push_i8 17
define_field "176"
push_2 2
define_field "177"
push_3 3
define_field "178"
push_i8 15
define_field "179"
push_3 3
define_field "180"
push_1 1
define_field "181"
push_1 1
define_field "182"
push_i8 15
define_field "183"
push_4 4
define_field "184"
push_1 1
define_field "185"
push_2 2
define_field "186"
push_i8 16
define_field "187"
push_1 1
define_field "188"
push_2 2
define_field "189"
push_3 3
define_field "190"
push_i8 16
define_field "191"
push_1 1
define_field "192"
push_1 1
define_field "193"
push_4 4
define_field "194"
push_3 3
define_field "195"
push_3 3
define_field "196"
push_4 4
define_field "197"
push_1 1
define_field "198"
push_4 4
define_field "199"
push_0 0
define_field "200"
push_0 0
define_field "201"
push_0 0
define_field "202"
push_i16 256
define_field "203"
push_i8 17
define_field "204"
push_3 3
define_field "205"
push_4 4
define_field "206"
push_i8 15
define_field "207"
push_4 4
define_field "208"
push_0 0
define_field "209"
push_0 0
define_field "210"
push_i8 11
define_field "211"
push_4 4
define_field "212"
push_3 3
define_field "213"
push_i8 16
define_field "214"
push_0 0
define_field "215"
push_0 0
define_field "216"
push_4 4
define_field "217"
push_1 1
define_field "218"
push_4 4
define_field "219"
push_0 0
define_field "220"
push_0 0
define_field "221"
push_0 0
define_field "222"
push_1 1
define_field "223"
push_3 3
define_field "224"
push_0 0
define_field "225"
push_4 4
define_field "226"
push_i8 12
define_field "227"
push_0 0
define_field "228"
push_i8 27
define_field "229"
push_i8 13
define_field "230"
push_0 0
define_field "231"
push_0 0
define_field "232"
push_0 0
define_field "233"
push_i16 145
define_field "234"
push_0 0
define_field "235"
dup
put_var program
gpt搓个脚本提取出来
import re
def extract_numbers(data):
# 使用正则表达式匹配指令后的数字
pattern = re.compile(r'\bpush_\w+\s+(-?\d+)')
# 查找所有匹配的数字
numbers = pattern.findall(data)
# 将匹配的数字转换为整数并返回
return [int(num) for num in numbers]
# 示例数据
data = """
...
"""
# 提取数字并存储到数组中
numbers = extract_numbers(data)
print(numbers)
并不是所有的值都在0-17之间,这是因为该指令集是几个opcode一组,因为有参数
像1指令是mov一个数进入寄存器内,第一个opcode是1,第二个是寄存器的编号1,第3-6个是小端序存储的数据
矩阵杯初赛逆向题解 – z221x-blog
参考该文章写log
#log
program = [1, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 16, 1, 1, 1, 1, 2, 0, 0, 0, 8, 2, 3, 1, 17, 3, 2, 15, 2, 3, 3, 16, 2, 1, 2, 1, 2, 0, 0, 0, 1, 3, 1, 2, 12, 1, 256, 13, 0, 0, 0, 18, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 15, 2, 1, 0, 3, 1, 2, 15, 2, 2, 0, 3, 1, 2, 1, 2, 0, 0, 0, 256, 17, 1, 2, 15, 2, 1, 1, 15, 3, 1, 0, 16, 1, 0, 2, 16, 1, 1, 3, 1, 2, 0, 0, 0, 1, 3, 0, 2, 12, 0, 256, 13, 0, 0, 0, 71, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 1, 3, 0, 0, 0, 1, 3, 1, 3, 1, 3, 0, 0, 0, 256, 17, 1, 3, 15, 3, 1, 1, 3, 2, 3, 1, 3, 0, 0, 0, 256, 17, 2, 3, 15, 3, 1, 1, 15, 4, 1, 2, 16, 1, 2, 3, 16, 1, 1, 4, 3, 3, 4, 1, 4, 0, 0, 0, 256, 17, 3, 4, 15, 4, 0, 0, 11, 4, 3, 16, 0, 0, 4, 1, 4, 0, 0, 0, 1, 3, 0, 4, 12, 0, 27, 13, 0, 0, 0, 145, 0]
ip = 0
while True:
if ip > 230:
break
if program[ip] == 0:
pass
elif program[ip] == 1:
print("%d mov reg[%d],%d" % (ip, program[ip + 1], ((program[ip+2]*16+program[ip+3])*16+program[ip+4])*16+program[ip+5]))
ip += 6
elif program[ip] == 2:
print("%d mov reg[%d],reg[%d]" % (ip, program[ip + 1],program[ip+2]))
ip += 3
elif program[ip] == 3:
print("%d div reg[%d],reg[%d]" % (ip, program[ip + 1], program[ip + 2]))
ip += 3
elif program[ip] == 4:
print("%d add reg[%d],reg[%d]" % (ip, program[ip + 1], program[ip + 2]))
ip += 3
elif program[ip] == 5:
print(ip, "%d REG[%d] *= REG[%d]" % (ip, program[ip + 1], program[ip + 2]))
ip += 3
elif program[ip] == 6:
print(ip, "%d REG[%d] = int(REG[%d] % REG[%d])" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))
ip += 3
elif program[ip] == 7:
print(ip, "%d REG[%d] = REG[%d] >> REG[%d]" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))
ip += 3
elif program[ip] == 8:
print("%d REG[%d] = REG[%d] << REG[%d]" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))
ip += 3
elif program[ip] == 9:
print("%d REG[%d] = REG[%d] | REG[%d]" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))
ip += 3
elif program[ip] == 10:
print("%d REG[%d] = REG[%d] ^ REG[%d]" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))
ip += 3
elif program[ip] == 11:
print("%d REG[%d] = REG[%d] & REG[%d]" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))
ip += 3
elif program[ip] == 12:
print("%d cmp reg[%d],%d" % (ip, program[ip + 1], program[ip + 2]))
ip += 3
elif program[ip] == 13:
print("%d jne %d" % (ip, ((program[ip + 1] * 16 + program[ip + 2]) * 16 + program[ip + 3]) * 16 + program[ip + 4]))
print("flag += 1")
ip += 5
elif program[ip] == 14:
print("%d jmp %d" % (ip, ((program[ip + 1] * 16 + program[ip + 2]) * 16 + program[ip + 3]) * 16 + program[ip + 4]))
ip += 5
elif program[ip] == 15:
print(ip, "REG[%d] = buf[%d][REG[%d]]" % (program[ip + 1], program[ip + 2], program[ip + 3]))
ip += 4
elif program[ip] == 16:
print(ip, "buf[%d][REG[%d]] = REG[%d]" % (program[ip + 1], program[ip + 2], program[ip + 3]))
ip += 4
elif program[ip] == 17:
print("%d sub reg[%d],reg[%d]" % (ip, program[ip + 1], program[ip + 2]))
ip += 3
0 mov reg[1],0
6 mov reg[2],0
12 mov reg[3],0
18 buf[1][REG[1]] = REG[1]
22 mov reg[2],8
28 mov reg[3],reg[1]
31 sub reg[3],reg[2]
34 REG[2] = buf[3][REG[3]]
38 buf[2][REG[1]] = REG[2]
42 mov reg[2],1
48 div reg[1],reg[2]
51 cmp reg[1],256
54 jne 18
flag += 1
59 mov reg[0],0
65 mov reg[1],0
71 REG[2] = buf[1][REG[0]]
75 div reg[1],reg[2]
78 REG[2] = buf[2][REG[0]]
82 div reg[1],reg[2]
85 mov reg[2],256
91 sub reg[1],reg[2]
94 REG[2] = buf[1][REG[1]]
98 REG[3] = buf[1][REG[0]]
102 buf[1][REG[0]] = REG[2]
106 buf[1][REG[1]] = REG[3]
110 mov reg[2],1
116 div reg[0],reg[2]
119 cmp reg[0],256
122 jne 71
flag += 1
127 mov reg[0],0
133 mov reg[1],0
139 mov reg[2],0
145 mov reg[3],1
151 div reg[1],reg[3]
154 mov reg[3],256
160 sub reg[1],reg[3]
163 REG[3] = buf[1][REG[1]]
167 div reg[2],reg[3]
170 mov reg[3],256
176 sub reg[2],reg[3]
179 REG[3] = buf[1][REG[1]]
183 REG[4] = buf[1][REG[2]]
187 buf[1][REG[2]] = REG[3]
191 buf[1][REG[1]] = REG[4]
195 div reg[3],reg[4]
198 mov reg[4],256
204 sub reg[3],reg[4]
207 REG[4] = buf[0][REG[0]]
211 REG[4] = REG[4] & REG[3]
214 buf[0][REG[0]] = REG[4]
218 mov reg[4],1
224 div reg[0],reg[4]
227 cmp reg[0],27
230 jne 145
flag += 1
从数组的套娃格式和256这样的特征值可以猜测RC4,不过211指令似乎应该是异或,不知道为什么打出来是与
然后就是解密
这部分buf数组看长度像key
array_from 0
array_from 0
array_from 0
push_i16 222
push_i16 173
push_i16 190
push_i8 15
push_i8 15
push_i16 190
push_i16 173
push_i16 222
array_from 8
array_from 4
dup
put_var buf
buf = [222, 173, 190, 15, 15, 190, 173, 222]
push_0 0
push_0 0
push_0 0
push_0 0
array_from 4
dup
put_var REG
put_loc0 0: "<ret>"
push_0 0
dup
put_var FLAG
寄存器和标志位
push_i8 32
push_i16 213
push_i16 149
push_i16 247
push_i8 50
push_i8 47
push_i8 116
push_i16 149
push_i8 112
push_i16 249
push_i16 206
push_i8 89
push_i16 213
push_i16 222
push_i16 155
push_i16 194
push_i8 81
push_i8 18
push_i16 212
push_i16 246
push_i8 96
push_i16 190
push_i16 150
push_i8 51
push_i8 12
push_i8 69
push_3 3
array_from 27
dup
put_var ans
这部分应该就是密文
ans = [ 32, 213, 149, 247, 50, 47, 116, 149, 112, 249, 206, 89, 213, 222, 155, 194, 81, 18, 212, 246, 96, 190, 150, 51, 12, 69, 3 ]
但是传统RC4解不出来,他魔改了!!!真不是人啊
结合GPT的整理理解吧……
def custom_algorithm(key, v):
buf = [[0]*256 for _ in range(4)]
reg = [0] * 5
flag = 0
# First block of instructions
reg[1] = 0
reg[2] = 0
reg[3] = 0
buf[1][reg[1]] = reg[1]
reg[2] = 8
reg[3] = reg[1]
reg[3] -= reg[2]
reg[2] = buf[3][reg[3]]
buf[2][reg[1]] = reg[2]
reg[2] = 1
reg[1] //= reg[2]
if reg[1] != 256:
while True:
buf[1][reg[1]] = reg[1]
reg[2] = 8
reg[3] = reg[1]
reg[3] -= reg[2]
reg[2] = buf[3][reg[3]]
buf[2][reg[1]] = reg[2]
reg[2] = 1
reg[1] //= reg[2]
if reg[1] == 256:
break
flag += 1
# Second block of instructions
reg[0] = 0
reg[1] = 0
reg[2] = buf[1][reg[0]]
reg[1] //= reg[2]
reg[2] = buf[2][reg[0]]
reg[1] //= reg[2]
reg[2] = 256
reg[1] -= reg[2]
reg[2] = buf[1][reg[1]]
reg[3] = buf[1][reg[0]]
buf[1][reg[0]] = reg[2]
buf[1][reg[1]] = reg[3]
reg[2] = 1
reg[0] //= reg[2]
if reg[0] != 256:
while True:
reg[2] = buf[1][reg[0]]
reg[1] //= reg[2]
reg[2] = buf[2][reg[0]]
reg[1] //= reg[2]
reg[2] = 256
reg[1] -= reg[2]
reg[2] = buf[1][reg[1]]
reg[3] = buf[1][reg[0]]
buf[1][reg[0]] = reg[2]
buf[1][reg[1]] = reg[3]
reg[2] = 1
reg[0] //= reg[2]
if reg[0] == 256:
break
flag += 1
# Third block of instructions
reg[0] = 0
reg[1] = 0
reg[2] = 0
reg[3] = 1
reg[1] //= reg[3]
reg[3] = 256
reg[1] -= reg[3]
reg[3] = buf[1][reg[1]]
reg[2] //= reg[3]
reg[3] = 256
reg[2] -= reg[3]
reg[3] = buf[1][reg[1]]
reg[4] = buf[1][reg[2]]
buf[1][reg[2]] = reg[3]
buf[1][reg[1]] = reg[4]
reg[3] //= reg[4]
reg[4] = 256
reg[3] -= reg[4]
reg[4] = buf[0][reg[0]]
reg[4] &= reg[3]
buf[0][reg[0]] = reg[4]
reg[4] = 1
reg[0] //= reg[4]
if reg[0] != 27:
while True:
reg[1] //= reg[3]
reg[3] = 256
reg[1] -= reg[3]
reg[3] = buf[1][reg[1]]
reg[2] //= reg[3]
reg[3] = 256
reg[2] -= reg[3]
reg[3] = buf[1][reg[1]]
reg[4] = buf[1][reg[2]]
buf[1][reg[2]] = reg[3]
buf[1][reg[1]] = reg[4]
reg[3] //= reg[4]
reg[4] = 256
reg[3] -= reg[4]
reg[4] = buf[0][reg[0]]
reg[4] &= reg[3]
buf[0][reg[0]] = reg[4]
reg[4] = 1
reg[0] //= reg[4]
if reg[0] == 27:
break
flag += 1
return buf[0][:27]
# Example usage
key = [ord(c) for c in "examplekey"] # Replace "examplekey" with the actual key
v = [ord(c) for c in "examplevalue"] # Replace "examplevalue" with the actual v
result = custom_algorithm(key, v)
print(''.join(chr(c) for c in result))
#jvm wp
def rc4(key, v):
s = list(range(256))
k = [key[i % 8] for i in range(256)]
j = 0
# Initial permutation of s
for i in range(256):
j = (j + s[i] + k[i]) % 256
s[i], s[j] = s[j], s[i] # Swap s[i] and s[j]
j = 0
s2 = [0] * 256
# Further permutation and creation of s2
for i in range(1, 256):
j = (j + s[i]) % 256
s2[i - 1] = (s[i] + s[j]) % 256
s[i], s[j] = s[j], s[i] # Swap s[i] and s[j]
# XOR s2 with v and print the result
result = ''.join(chr(s2[i] ^ v[i]) for i in range(27))
return result
data = [32, 213, 149, 247, 50, 47, 116, 149, 112, 249, 206, 89, 213, 222, 155, 194, 81, 18, 212, 246, 96, 190, 150, 51, 12, 69, 3]
key = [222, 173, 190, 15, 15, 190, 173, 222]
decrypted = rc4(key, data)
print(decrypted)
#flag{js3ng1n7lik3m1r0uter!}
主要是换盒子的时候改了一些算法,s2是逆序异或的
要是动调跑出密钥流就很方便了,但不知道怎么做到的
矩阵杯 2024 战队攻防对抗赛初赛 Writeup | CTF导航