矩阵杯2024 Re wp 前两题

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导航

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/696611.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue14-监视属性

一、天气案例 1-1、方式一&#xff1a;{{三目运算符}} 1-2、方式二&#xff1a;计算属性 1-3、方式三&#xff1a;click中写简单逻辑 click里面可以写简单的逻辑语句。不用this 解决方式&#xff1a; 小结&#xff1a; 绑定事件的时候&#xff0c;xxx"yyy" xxx&…

RISC-V MCU IDE MRS(MounRiver Studio)开发 编译后打印FLASH及RAM使用占比信息

以RISC-V MCU IDE MounRiver Studio(MRS)为例&#xff0c;首先我们选中目标工程&#xff0c;点击工具栏工程属性按钮&#xff0c;打开工程属性配置页&#xff1a; 在C/C Build->Settings->Tool Settings选项列表中单击GNU RISC-V Cross C Linker->Miscellaneous&#…

【PowerDesigner】创建和管理CDM之使用实体间关系

目录 &#x1f30a;1. PowerDesigner简介 &#x1f30d;1.1 常用模型文件 &#x1f30d;1.2 PowerDesigner使用环境 &#x1f30a;2. 创建和管理CDM &#x1f30d;​​​​​​2.1 新建CDM &#x1f30d;2.2 使用实体间关系 &#x1f30c;a. 使用联系 &#x1f30c;b. …

Kafka的分区副本机制

目录 生产者的分区写入策略 轮询策略 随机策略 按key分配策略 乱序分区 自定义分区策略 实现步骤&#xff1a; 消费者组Rebalance机制 Rebalance触发时机 Rebalance的不良影响 消费者分区分配策略 Range范围分配策略 RoundRobin轮询策略 Stricky粘性分配策略 生产…

【机器学习】基于卷积LSTM的视频预测

1. 引言 1.1 LSTM是什么 LSTM&#xff08;Long Short-Term Memory&#xff09;是一种特殊的循环神经网络&#xff08;RNN&#xff09;变体&#xff0c;旨在解决传统RNN在处理长序列数据时遇到的梯度消失和梯度爆炸问题。LSTM通过引入门控机制和细胞状态的概念&#xff0c;使得…

JavaScript基础用法(变量定义、输入输出、转义符、注释和编码规范)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

三极管十大品牌

三极管十大品牌-三极管品牌-晶体三极管哪个品牌好-Maigoo品牌榜

攻防世界---misc---gif

1、题目描述 2、下载附件&#xff0c;是一堆黑白图片&#xff0c;看到这里我一头雾水 3、看别人写的wp&#xff0c;说是白色表示0&#xff0c;黑色表示1。按照顺序写出来后得到 4、解码的时候&#xff0c;把逗号去掉。二进制转字符串得到&#xff1a; 5、 flag{FuN_giF}

C语言之main函数的返回值(在linux中执行shell脚本并且获取返回值)

一&#xff1a;函数为什么要返回值 &#xff08;1&#xff09;函数 在设计的时候是设计了参数和返回值&#xff0c;参数是函数的输入&#xff0c;返回值是数据的输出 &#xff08;2&#xff09;因为函数需要对外输出数据&#xff08;实际上是函数运行的一些结果值&#xff09;…

LabVIEW汽车电机测试系统

1. 背景 随着电动汽车的快速发展&#xff0c;汽车电机作为电动汽车的核心部件&#xff0c;其性能评估变得尤为重要。电机的功率、效率、转速等参数直接影响着电动汽车的性能和续航里程。因此&#xff0c;设计一套全面、准确的汽车电机测试系统对于提高电动汽车的性能和安全性具…

Redis 双写一致原理篇

前言 我们都知道,redis一般的作用是顶在mysql前面做一个"带刀侍卫"的角色,可以缓解mysql的服务压力,但是我们如何保证数据库的数据和redis缓存中的数据的双写一致呢,我们这里先说一遍流程,然后以流程为切入点来谈谈redis和mysql的双写一致性是如何保证的吧 流程 首先…

【Python】pandas中的read_excel()和to_excel()函数解析与代码实现

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大家关注其他专栏&#xff0c;我将分享Web前后端开发、人工智能、机器学习、深…

SQL159 每个创作者每月的涨粉率及截止当前的总粉丝量

描述 用户-视频互动表tb_user_video_log iduidvideo_idstart_timeend_timeif_followif_likeif_retweetcomment_id110120012021-09-01 10:00:002021-09-01 10:00:20011NULL210520022021-09-10 11:00:002021-09-10 11:00:30101NULL310120012021-10-01 10:00:002021-10-01 10:00…

-31-()

在终端运行时消除输入空格对程序的影响可以使用{在scanf后加“getchar()”或者在scanf&#xff08;“空格%d”,&a&#xff09;} 按位与和移位操作符只能用于整数且都要转位二进制后进行相应操作 不创建临时变量&#xff0c;实现两个数的交换&#xff1a;1——使用加减法&…

【全开源】多功能投票小程序系统源码(ThinkPHP+FastAdmin+Uniapp)

&#x1f680; 多功能投票小程序&#xff0c;让决策变得更简单&#xff01; 基于ThinkPHPFastAdminUniapp开发的多功能系统&#xff0c;支持图文投票、自定义选手报名内容、自定义主题色、礼物功能(高级授权)、弹幕功能(高级授权)、会员发布、支持数据库私有化部署&#xff0c…

本周重磅日程:美联储决议、中美通胀、苹果AI和英伟达拆股

当周重磅看点颇多&#xff1a;美联储FOMC将公布最新利率“点阵图”&#xff0c;中国5月金融数据、中美通胀数据将出炉&#xff0c;日本央行购债计划是否变动成为市场焦点&#xff0c;苹果2024全球开发者大会一系列AI功能将亮相&#xff1b;特斯拉2024股东大会上马斯克560亿美元…

Springboot结合redis实现关注推送

关注推送 Feed流的模式 Timeline:不做内容筛选&#xff0c;简单的按照内容发布时间排序。常用于好友与关注。例如朋友圈的时间发布排序。 优点:信息全面&#xff0c;不会有缺失。并且实现也相对简单 缺点:信息噪音较多&#xff0c;用户不一定感兴趣&#xff0c;内容获取效率…

Spring Boot整合Redis实现发布/订阅功能

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

来腾讯第4天,我已经焦虑昏了啊!

大家好&#xff0c;我是白露啊。 今天在看到一个实习生在抱怨&#xff0c;给我笑惨了。 标题是&#xff1a;“腾讯实习第4天&#xff0c;焦虑昏了”&#xff01; 他写道&#xff1a;“怎么办啊牛爷爷们&#xff0c;什么都不会。业务看不懂&#xff0c;文档看不懂&#xff0c;…

用 Python 撸一个 Web 服务器-第4章:动态渲染数据

上一章中为了尽快让 Todo List 程序跑起来&#xff0c;并没有完全按照 MVC 模式编写程序。这一章就让我们一起实现一个完整的 MVC 模式 Todo List 程序首页。 使用模型操作数据 我们来分析下请求 Todo List 程序首页时&#xff0c;模型层需要做哪些事情。当一个请求到达首页视…