矩阵杯2024 Re wp 前两题

news2024/9/20 10:40:38

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ROS学习记录:C++节点发布自定义地图

前言 ROS栅格地图格式 在了解了ROS地图消息包的数据结构后(链接在上)&#xff0c;本文将编写一个节点&#xff0c;发布地图消息包&#xff0c;看看在RViz中显示是什么效果。 一、准备 1、为了简单起见&#xff0c;发布一个两行四列的地图 2、为了便于观测&#xff0c;只对地…

textattack报错:不能导入自定义search_methods (cannot import name ‘xxx‘ from ‘xxx‘)

1. 报错信息 ImportError: cannot import name AAA from textattack.search_methods (/home/666/anaconda3/envs/textattack37_env/lib/python3.7/site-packages/textattack/search_methods/__init__.py)2. 出错简述 贴一段test1.py的模块导入 #建议使用&#xff01; import…

时钟影响ADC性能不仅仅是抖动

时钟影响ADC性能除了抖动&#xff0c;还有占空比。 在高速AD采样中&#xff0c;时钟占空比是非常重要的一个参数。时钟信号的上升沿控制ADC的采样&#xff0c;而下降沿控制着信号的保持&#xff0c;在一个周期内才可以完成量化输出&#xff0c;所以必须保持时钟的占空比为50%&…

Typora Markdown编辑器 for Mac v1.8.10 安装

Mac分享吧 文章目录 效果一、准备工作二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2. 应用程序显示软件图标&#xff0c;表示安装成功 三、运行调试1、修改主题2、显示文档列表&#xff0c;如下图3、查看版本信息 **安装完成&…

AI智能体做高考志愿填报分析

关注公众号&#xff0c;赠送AI/Python/Linux资料&#xff0c;对AI智能体有兴趣的朋友也可以添加一起交流 高考正在进行时&#xff0c;学生焦虑考试&#xff0c;家长们焦虑的则是高考志愿怎么填。毕竟一个好的学校&#xff0c;好的专业是进入社会的第一个敲门砖 你看张雪峰老师…

CvT(ICCV 2021)论文与代码解读

paper&#xff1a;CvT: Introducing Convolutions to Vision Transformers official implementation&#xff1a;https://github.com/microsoft/CvT 出发点 该论文的出发点是改进Vision Transformer (ViT) 的性能和效率。传统的ViT在处理图像分类任务时虽然表现出色&#xf…

xilinx的Aurora8B10B的IP仿真及上板测试(高速收发器十七)

前文讲解了Aurora8B10B协议原理及xilinx相关IP&#xff0c;本文讲解如何设置该IP&#xff0c;并且通过示例工程完成该IP的仿真和上板。 1、生成Aurora8B10B IP 如下图所示&#xff0c;首先在vivado的IP catalog中输入Aurora 8B10B&#xff0c;双击该IP。 图1 查找Aurora 8B10…

【Python】成功解决SyntaxError: invalid syntax

【Python】成功解决SyntaxError: invalid syntax 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕&am…

cuda学习笔记(3)

一 CPU和GPU的区别 衡量处理器优劣的重要的两个指标&#xff1a; 延时性&#xff1a;同量的数据&#xff0c;所需要的处理时间 吞吐性&#xff1a;处理速度不快&#xff0c;但是每次处理量很大 GPU设计理念是最大化吞吐量&#xff0c;使用很小的控制单元对应很小的内存 cpu的设…

类和对象(下+)_const成员、初始化列表、友元、匿名对象

类和对象&#xff08;下&#xff09; 文章目录 类和对象&#xff08;下&#xff09;前言一、const成员二、友元1.友元函数2.友元类 三、初始化列表四、explicit关键字五、匿名对象总结 前言 static成员、内部类、const成员、初始化列表、友元、匿名对象 一、const成员 将cons…

cleanmymac清理时要一直输入密码 CleanMyMac X一直提示输入密码的解决方案

CleanMyMac X是一款专业的Mac清理软件&#xff0c;可智能清理mac磁盘垃圾和多余语言安装包&#xff0c;快速释放电脑内存&#xff0c;轻松管理和升级Mac上的应用。同时CleanMyMac X可以强力卸载恶意软件&#xff0c;修复系统漏洞&#xff0c;一键扫描和优化Mac系统。 在使用Cle…

LeetCode | 2022.将一维数组转变为二维数组

这道题思路比较简单&#xff0c;比较容易想到的是先判断m和n构成的二维数组在形式上是否可以由原来的数组转变而成&#xff0c;若不可以返回空数组&#xff0c;若可以直接用一个二重循环遍历一遍即可&#xff0c;时间复杂度 O ( n 2 ) O(n^2) O(n2) class Solution(object):de…

数据结构初阶 · 链式二叉树的部分问题

目录 前言&#xff1a; 1 链式二叉树的创建 2 前序 中序 后序遍历 3 树的节点个数 4 树的高度 5 树的叶子节点个数 6 树的第K层节点个数 前言&#xff1a; 链式二叉树我们在C语言阶段已经实现了&#xff0c;这里介绍的是涉及到的部分问题&#xff0c;比如求树的高度&am…

三、安全工程练习题(CISSP)

1.三、安全工程练习题(CISSP)

找素数第二、三种方法

文章目录 第一种 &#xff1a;使用标签第二种&#xff1a;本质是方法的分装 第一种 &#xff1a;使用标签 没有使用信号量。break和continue作用范围只是最近的循环&#xff0c;无法控制外部循环。 此时使用标签 对外部循环进行操作。 package com.zhang; /* 找素数 第二种方…

【已解决】FileNotFoundError: [Errno 3] No such file or directory: ‘xxx‘

&#x1f60e; 作者介绍&#xff1a;我是程序员行者孙&#xff0c;一个热爱分享技术的制能工人。计算机本硕&#xff0c;人工制能研究生。公众号&#xff1a;AI Sun&#xff0c;视频号&#xff1a;AI-行者Sun &#x1f388; 本文专栏&#xff1a;本文收录于《AI实战中的各种bug…

【C语言】03.分支结构

本文用以介绍分支结构&#xff0c;主要的实现方式为if语句和switch语句。 一、if语句 1.1 if语句 if (表达式)语句表达式为真则执行语句&#xff0c;为假就不执行。在C语言中&#xff0c;0表示假&#xff0c;非0表示真.下图表示if的执行过程&#xff1a; 1.2 else语句 当…

数字孪生概念、数字孪生技术架构、数字孪生应用场景,深度长文学习

一、数字孪生起源与发展 1.1 数字孪生产生背景 数字孪生的概念最初由Grieves教授于2003年在美国密歇根大学的产品全生命周期管理课程上提出&#xff0c;并被定义为三维模型&#xff0c;包括实体产品、虚拟产品以及二者间的连接&#xff0c;如下图所示&#xff1a; 2011年&…

32位和64位的Windows7均不支持UEFI启动方式?试试看!

前言 今天小白突然想起&#xff1a;自己已经接近8年没有安装过32位的Windows系统了&#xff0c;这8年装的上百台电脑都是用的64位Windows。 今天 闲来无事 嗯……应该算是有小伙伴提出了个问题&#xff1a; 这位小伙伴表示&#xff1a;自己无论安装32位还是64位的Windows7都…

OSPF LSA头部详解

LSA概述 LSA是OSPF的本质 , 对于网工来说能否完成OSPF的排错就是基于OSPF的LSDB掌握程度 . 其中1/2类LAS是负责区域内部的 类似于设备的直连路由 . 加上对端的设备信息 3 类LSA是区域间的 指的是Area0和其他Area的区域间关系 , 设计多区域的初衷就是避免大型OSPF环境LSA太多…