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.8import 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 idef decrypt(enc, key):flag = ''for i in encdata:flag += chr(idx(i^95, key))return flagkey = 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 018 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 026 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 136 STORE_NAME 5 (flag)21 38 LOAD_NAME 2 (generate_key)40 LOAD_NAME 6 (len)42 LOAD_NAME 5 (flag)44 CALL_FUNCTION 146 CALL_FUNCTION 148 STORE_NAME 7 (key)22 50 LOAD_NAME 5 (flag)52 LOAD_METHOD 8 (encode)54 CALL_METHOD 056 STORE_NAME 9 (data)23 58 LOAD_NAME 3 (encrypt)60 LOAD_NAME 9 (data)62 LOAD_NAME 7 (key)64 CALL_FUNCTION 266 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 8426 76 LOAD_NAME 11 (print)78 LOAD_CONST 8 ('good')80 CALL_FUNCTION 182 POP_TOP>> 84 POP_BLOCK86 JUMP_FORWARD 12 (to 100)27 >> 88 POP_TOP90 POP_TOP92 POP_TOP28 94 POP_EXCEPT96 JUMP_FORWARD 2 (to 100)98 END_FINALLY>> 100 LOAD_CONST 1 (None)102 RETURN_VALUEDisassembly 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 18 CALL_FUNCTION 110 STORE_FAST 1 (key)8 12 LOAD_GLOBAL 2 (random)14 LOAD_METHOD 3 (seed)16 LOAD_FAST 0 (seed_value)18 CALL_METHOD 120 POP_TOP9 22 LOAD_GLOBAL 2 (random)24 LOAD_METHOD 4 (shuffle)26 LOAD_FAST 1 (key)28 CALL_METHOD 130 POP_TOP10 32 LOAD_GLOBAL 5 (bytes)34 LOAD_FAST 1 (key)36 CALL_FUNCTION 138 RETURN_VALUEDisassembly of <code object encrypt at 0x000001F1E47BA870, file "run.py", line 12>:14 0 LOAD_GLOBAL 0 (bytearray)2 CALL_FUNCTION 04 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_SUBSCR24 LOAD_CONST 1 (95)26 BINARY_XOR28 CALL_METHOD 130 POP_TOP32 JUMP_ABSOLUTE 1017 >> 34 LOAD_GLOBAL 2 (bytes)36 LOAD_FAST 2 (encrypted)38 CALL_FUNCTION 140 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 binasciidef print_metadata(fp):amagic = 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)
codeargcount 0nlocals 0stacksize 6flags 0040codeb'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 018 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 026 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 136 STORE_NAME 5 (flag)21 38 LOAD_NAME 2 (generate_key)40 LOAD_NAME 6 (len)42 LOAD_NAME 5 (flag)44 CALL_FUNCTION 146 CALL_FUNCTION 148 STORE_NAME 7 (key)22 50 LOAD_NAME 5 (flag)52 LOAD_METHOD 8 (encode)54 CALL_METHOD 056 STORE_NAME 9 (data)23 58 LOAD_NAME 3 (encrypt)60 LOAD_NAME 9 (data)62 LOAD_NAME 7 (key)64 CALL_FUNCTION 266 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 8426 76 LOAD_NAME 11 (print)78 LOAD_CONST 8 ('good')80 CALL_FUNCTION 182 POP_TOP>> 84 POP_BLOCK86 JUMP_FORWARD 12 (to 100)27 >> 88 POP_TOP90 POP_TOP92 POP_TOP28 94 POP_EXCEPT96 JUMP_FORWARD 2 (to 100)98 END_FINALLY>> 100 LOAD_CONST 1 (None)102 RETURN_VALUEconsts0Noneb'\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'codeargcount 1nlocals 2stacksize 3flags 0043codeb'740074016401830183017d017402a0037c00a10101007402a0047c01a101'b'010074057c0183015300'7 0 LOAD_GLOBAL 0 (list)2 LOAD_GLOBAL 1 (range)4 LOAD_CONST 1 (256)6 CALL_FUNCTION 18 CALL_FUNCTION 110 STORE_FAST 1 (key)8 12 LOAD_GLOBAL 2 (random)14 LOAD_METHOD 3 (seed)16 LOAD_FAST 0 (seed_value)18 CALL_METHOD 120 POP_TOP9 22 LOAD_GLOBAL 2 (random)24 LOAD_METHOD 4 (shuffle)26 LOAD_FAST 1 (key)28 CALL_METHOD 130 POP_TOP10 32 LOAD_GLOBAL 5 (bytes)34 LOAD_FAST 1 (key)36 CALL_FUNCTION 138 RETURN_VALUEconstsNone256names ('list', 'range', 'random', 'seed', 'shuffle', 'bytes')varnames ('seed_value', 'key')freevars ()cellvars ()filename 'run.py'name 'generate_key'firstlineno 5lnotab b'00020c010a010a01''generate_key'codeargcount 2nlocals 4stacksize 5flags 0043codeb'740083007d027c0044005d167d037c02a0017c017c03190064014100a101'b'0100710a74027c0283015300'14 0 LOAD_GLOBAL 0 (bytearray)2 CALL_FUNCTION 04 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_SUBSCR24 LOAD_CONST 1 (95)26 BINARY_XOR28 CALL_METHOD 130 POP_TOP32 JUMP_ABSOLUTE 1017 >> 34 LOAD_GLOBAL 2 (bytes)36 LOAD_FAST 2 (encrypted)38 CALL_FUNCTION 140 RETURN_VALUEconstsNone95names ('bytearray', 'append', 'bytes')varnames ('data', 'key', 'encrypted', 'byte')freevars ()cellvars ()filename 'run.py'name 'encrypt'firstlineno 12lnotab 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 1lnotab 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: runVMlocals:0: var flag1: var regId2: var num3: var regid14: var regid25: var regid6: var bufIdx7: var dataIdxstack_size: 6opcodes:push_0 0put_loc0 0: flag2: get_var programget_var ipget_array_elpush_0 0neqif_false 890get_var programget_var ipget_array_elpush_1 1eqif_false8 61get_var getRegcall0 0put_loc1 1: regIdget_var getNumcall0 0put_loc2 2: numget_var setRegget_loc1 1: regIdget_loc2 2: numcall2 2dropgoto16 87361: get_var programget_var ipget_array_elpush_2 2eqif_false8 104get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var setReg2get_loc3 3: regid1get_loc8 4: regid2call2 2dropgoto16 873104: get_var programget_var ipget_array_elpush_3 3eqif_false8 147get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var addRegget_loc3 3: regid1get_loc8 4: regid2call2 2dropgoto16 873147: get_var programget_var ipget_array_elpush_4 4eqif_false8 190get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var subRegget_loc3 3: regid1get_loc8 4: regid2call2 2dropgoto16 873190: get_var programget_var ipget_array_elpush_5 5eqif_false8 247get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var REGget_loc3 3: regid1to_propkey2get_var REGget_loc3 3: regid1get_array_elget_var REGget_loc8 4: regid2get_array_elmulput_array_elgoto16 873247: get_var programget_var ipget_array_elpush_6 6eqif_false8 310get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var REGget_loc3 3: regid1to_propkey2get_var parseIntget_var REGget_loc3 3: regid1get_array_elget_var REGget_loc8 4: regid2get_array_elmodcall1 1put_array_elgoto16 873310: get_var programget_var ipget_array_elpush_7 7eqif_false8 367get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var REGget_loc3 3: regid1to_propkey2get_var REGget_loc3 3: regid1get_array_elget_var REGget_loc8 4: regid2get_array_elsarput_array_elgoto16 873367: get_var programget_var ipget_array_elpush_i8 8eqif_false8 425get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var REGget_loc3 3: regid1to_propkey2get_var REGget_loc3 3: regid1get_array_elget_var REGget_loc8 4: regid2get_array_elshlput_array_elgoto16 873425: get_var programget_var ipget_array_elpush_i8 9eqif_false8 483get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var REGget_loc3 3: regid1to_propkey2get_var REGget_loc3 3: regid1get_array_elget_var REGget_loc8 4: regid2get_array_elorput_array_elgoto16 873483: get_var programget_var ipget_array_elpush_i8 10eqif_false8 541get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var REGget_loc3 3: regid1to_propkey2get_var REGget_loc3 3: regid1get_array_elget_var REGget_loc8 4: regid2get_array_elxorput_array_elgoto16 873541: get_var programget_var ipget_array_elpush_i8 11eqif_false8 599get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var REGget_loc3 3: regid1to_propkey2get_var REGget_loc3 3: regid1get_array_elget_var REGget_loc8 4: regid2get_array_elandput_array_elgoto16 873599: get_var programget_var ipget_array_elpush_i8 12eqif_false8 641get_var getRegcall0 0put_loc1 1: regIdget_var getBytecall0 0put_loc2 2: numget_var cmpRegget_loc1 1: regIdget_loc2 2: numcall2 2dropgoto16 873641: get_var programget_var ipget_array_elpush_i8 13eqif_false8 670get_var jneIpcall0 0droppush_1 1inc_loc 0: flaggoto16 873670: get_var programget_var ipget_array_elpush_i8 14eqif_false8 696get_var jmpIpcall0 0dropgoto16 873696: get_var programget_var ipget_array_elpush_i8 15eqif_false8 764get_var getRegcall0 0put_loc8 5: regidget_var getBytecall0 0put_loc8 6: bufIdxget_var getBytecall0 0put_loc8 7: dataIdxget_var REGget_loc8 5: regidto_propkey2get_var bufget_loc8 6: bufIdxget_array_elget_var REGget_loc8 7: dataIdxget_array_elget_array_elput_array_elgoto8 873764: get_var programget_var ipget_array_elpush_i8 16eqif_false8 832get_var getBytecall0 0put_loc8 6: bufIdxget_var getBytecall0 0put_loc8 7: dataIdxget_var getRegcall0 0put_loc8 5: regidget_var bufget_loc8 6: bufIdxget_array_elget_var REGget_loc8 7: dataIdxget_array_elto_propkey2get_var REGget_loc8 5: regidget_array_elput_array_elgoto8 873832: get_var programget_var ipget_array_elpush_i8 17eqif_false8 873get_var getRegcall0 0put_loc3 3: regid1get_var getRegcall0 0put_loc8 4: regid2get_var modRegget_loc3 3: regid1get_loc8 4: regid2call2 2drop873: get_var ippush_1 1divdupput_var ipdropgoto16 2890: 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 = 0ip = 0while True:opcode = program[ip]if opcode == 0:breakelif 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 += 1elif 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 除以 1result = ip_value / 1# 复制结果result_copy = result# 将结果存储到变量 ipip = result_copy# 弹出堆栈顶部的值(在这里实际上不需要,因为 result_copy 已经存储了值)# 获取变量 program 的值program_value = program# 获取变量 ip 的值(已经在上面更新)ip_value = ip# 从数组 program 中获取索引为 ip_value 的元素array_element = program_value[int(ip_value)]# 返回获取的数组元素return array_elementdef getNum():# 初始化局部变量 sum 和 isum = 0i = 0# 循环执行操作while i < 4:ip = ip // 1sum += program[ip] // 16i += 1return sumdef setReg(regid, data):# 将 data 存入 regid 索引处的数组中REG[regid] = data# 返回 undefinedreturn Nonedef setReg2(regid1, regid2):# 将 regid2 索引处的值存入 regid1 索引处REG[regid1] = REG[regid2]# 返回 undefinedreturn Nonedef 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 Nonedef 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 Nonedef 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 Nonedef 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 存储到变量 FLAGFLAG = 1else:# 否则返回 undefined(在Python中用 None 表示)return None# 返回 undefined(在Python中用 None 表示)return Nonedef jneIp():# 获取 getNum 函数的返回值addrTrue = getNum()# 如果 FLAG 不等于 1,则跳转到 addrTrue+1 处if FLAG != 1:ip = addrTrue + 1FLAG = 0return Noneelse:FLAG = 0return Nonedef jmpIp():# 获取 getNum 函数的返回值addr = getNum()# 将 ip 设置为 addr + 1ip = addr + 1return Nonedef getByte():# 计算并获取 program[ip] 的值byte = program[ip // 1]return byte
然后就是要通过opcode打印log,看看指令是什么
在eval函数开头可以看到一些变量的定义
比如说这个是定义ip
push_0 0
dup
put_var ip
这部分是定义program,稍加分析可以知道是opcode
push_1 1push_1 1push_0 0push_0 0push_0 0push_0 0push_1 1push_2 2push_0 0push_0 0push_0 0push_0 0push_1 1push_3 3push_0 0push_0 0push_0 0push_0 0push_i8 16push_1 1push_1 1push_1 1push_1 1push_2 2push_0 0push_0 0push_0 0push_i8 8push_2 2push_3 3push_1 1push_i8 17array_from 32push_3 3define_field "32"push_2 2define_field "33"push_i8 15define_field "34"push_2 2define_field "35"push_3 3define_field "36"push_3 3define_field "37"push_i8 16define_field "38"push_2 2define_field "39"push_1 1define_field "40"push_2 2define_field "41"push_1 1define_field "42"push_2 2define_field "43"push_0 0define_field "44"push_0 0define_field "45"push_0 0define_field "46"push_1 1define_field "47"push_3 3define_field "48"push_1 1define_field "49"push_2 2define_field "50"push_i8 12define_field "51"push_1 1define_field "52"push_i16 256define_field "53"push_i8 13define_field "54"push_0 0define_field "55"push_0 0define_field "56"push_0 0define_field "57"push_i8 18define_field "58"push_1 1define_field "59"push_0 0define_field "60"push_0 0define_field "61"push_0 0define_field "62"push_0 0define_field "63"push_0 0define_field "64"push_1 1define_field "65"push_1 1define_field "66"push_0 0define_field "67"push_0 0define_field "68"push_0 0define_field "69"push_0 0define_field "70"push_i8 15define_field "71"push_2 2define_field "72"push_1 1define_field "73"push_0 0define_field "74"push_3 3define_field "75"push_1 1define_field "76"push_2 2define_field "77"push_i8 15define_field "78"push_2 2define_field "79"push_2 2define_field "80"push_0 0define_field "81"push_3 3define_field "82"push_1 1define_field "83"push_2 2define_field "84"push_1 1define_field "85"push_2 2define_field "86"push_0 0define_field "87"push_0 0define_field "88"push_0 0define_field "89"push_i16 256define_field "90"push_i8 17define_field "91"push_1 1define_field "92"push_2 2define_field "93"push_i8 15define_field "94"push_2 2define_field "95"push_1 1define_field "96"push_1 1define_field "97"push_i8 15define_field "98"push_3 3define_field "99"push_1 1define_field "100"push_0 0define_field "101"push_i8 16define_field "102"push_1 1define_field "103"push_0 0define_field "104"push_2 2define_field "105"push_i8 16define_field "106"push_1 1define_field "107"push_1 1define_field "108"push_3 3define_field "109"push_1 1define_field "110"push_2 2define_field "111"push_0 0define_field "112"push_0 0define_field "113"push_0 0define_field "114"push_1 1define_field "115"push_3 3define_field "116"push_0 0define_field "117"push_2 2define_field "118"push_i8 12define_field "119"push_0 0define_field "120"push_i16 256define_field "121"push_i8 13define_field "122"push_0 0define_field "123"push_0 0define_field "124"push_0 0define_field "125"push_i8 71define_field "126"push_1 1define_field "127"push_0 0define_field "128"push_0 0define_field "129"push_0 0define_field "130"push_0 0define_field "131"push_0 0define_field "132"push_1 1define_field "133"push_1 1define_field "134"push_0 0define_field "135"push_0 0define_field "136"push_0 0define_field "137"push_0 0define_field "138"push_1 1define_field "139"push_2 2define_field "140"push_0 0define_field "141"push_0 0define_field "142"push_0 0define_field "143"push_0 0define_field "144"push_1 1define_field "145"push_3 3define_field "146"push_0 0define_field "147"push_0 0define_field "148"push_0 0define_field "149"push_1 1define_field "150"push_3 3define_field "151"push_1 1define_field "152"push_3 3define_field "153"push_1 1define_field "154"push_3 3define_field "155"push_0 0define_field "156"push_0 0define_field "157"push_0 0define_field "158"push_i16 256define_field "159"push_i8 17define_field "160"push_1 1define_field "161"push_3 3define_field "162"push_i8 15define_field "163"push_3 3define_field "164"push_1 1define_field "165"push_1 1define_field "166"push_3 3define_field "167"push_2 2define_field "168"push_3 3define_field "169"push_1 1define_field "170"push_3 3define_field "171"push_0 0define_field "172"push_0 0define_field "173"push_0 0define_field "174"push_i16 256define_field "175"push_i8 17define_field "176"push_2 2define_field "177"push_3 3define_field "178"push_i8 15define_field "179"push_3 3define_field "180"push_1 1define_field "181"push_1 1define_field "182"push_i8 15define_field "183"push_4 4define_field "184"push_1 1define_field "185"push_2 2define_field "186"push_i8 16define_field "187"push_1 1define_field "188"push_2 2define_field "189"push_3 3define_field "190"push_i8 16define_field "191"push_1 1define_field "192"push_1 1define_field "193"push_4 4define_field "194"push_3 3define_field "195"push_3 3define_field "196"push_4 4define_field "197"push_1 1define_field "198"push_4 4define_field "199"push_0 0define_field "200"push_0 0define_field "201"push_0 0define_field "202"push_i16 256define_field "203"push_i8 17define_field "204"push_3 3define_field "205"push_4 4define_field "206"push_i8 15define_field "207"push_4 4define_field "208"push_0 0define_field "209"push_0 0define_field "210"push_i8 11define_field "211"push_4 4define_field "212"push_3 3define_field "213"push_i8 16define_field "214"push_0 0define_field "215"push_0 0define_field "216"push_4 4define_field "217"push_1 1define_field "218"push_4 4define_field "219"push_0 0define_field "220"push_0 0define_field "221"push_0 0define_field "222"push_1 1define_field "223"push_3 3define_field "224"push_0 0define_field "225"push_4 4define_field "226"push_i8 12define_field "227"push_0 0define_field "228"push_i8 27define_field "229"push_i8 13define_field "230"push_0 0define_field "231"push_0 0define_field "232"push_0 0define_field "233"push_i16 145define_field "234"push_0 0define_field "235"dupput_var program
gpt搓个脚本提取出来
import redef 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 = 0while True:if ip > 230:breakif program[ip] == 0:passelif 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 += 6elif program[ip] == 2:print("%d mov reg[%d],reg[%d]" % (ip, program[ip + 1],program[ip+2]))ip += 3elif program[ip] == 3:print("%d div reg[%d],reg[%d]" % (ip, program[ip + 1], program[ip + 2]))ip += 3elif program[ip] == 4:print("%d add reg[%d],reg[%d]" % (ip, program[ip + 1], program[ip + 2]))ip += 3elif program[ip] == 5: print(ip, "%d REG[%d] *= REG[%d]" % (ip, program[ip + 1], program[ip + 2]))ip += 3elif program[ip] == 6:print(ip, "%d REG[%d] = int(REG[%d] % REG[%d])" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))ip += 3elif program[ip] == 7:print(ip, "%d REG[%d] = REG[%d] >> REG[%d]" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))ip += 3elif program[ip] == 8:print("%d REG[%d] = REG[%d] << REG[%d]" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))ip += 3elif program[ip] == 9:print("%d REG[%d] = REG[%d] | REG[%d]" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))ip += 3elif program[ip] == 10:print("%d REG[%d] = REG[%d] ^ REG[%d]" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))ip += 3elif program[ip] == 11:print("%d REG[%d] = REG[%d] & REG[%d]" % (ip, program[ip + 1], program[ip + 1], program[ip + 2]))ip += 3elif program[ip] == 12:print("%d cmp reg[%d],%d" % (ip, program[ip + 1], program[ip + 2]))ip += 3elif 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 += 5elif program[ip] == 14:print("%d jmp %d" % (ip, ((program[ip + 1] * 16 + program[ip + 2]) * 16 + program[ip + 3]) * 16 + program[ip + 4]))ip += 5elif program[ip] == 15:print(ip, "REG[%d] = buf[%d][REG[%d]]" % (program[ip + 1], program[ip + 2], program[ip + 3]))ip += 4elif program[ip] == 16:print(ip, "buf[%d][REG[%d]] = REG[%d]" % (program[ip + 1], program[ip + 2], program[ip + 3]))ip += 4elif 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 0array_from 0array_from 0push_i16 222push_i16 173push_i16 190push_i8 15push_i8 15push_i16 190push_i16 173push_i16 222array_from 8array_from 4dupput_var buf
buf = [222, 173, 190, 15, 15, 190, 173, 222]
push_0 0push_0 0push_0 0push_0 0array_from 4dupput_var REGput_loc0 0: "<ret>"push_0 0dupput_var FLAG
寄存器和标志位
push_i8 32push_i16 213push_i16 149push_i16 247push_i8 50push_i8 47push_i8 116push_i16 149push_i8 112push_i16 249push_i16 206push_i8 89push_i16 213push_i16 222push_i16 155push_i16 194push_i8 81push_i8 18push_i16 212push_i16 246push_i8 96push_i16 190push_i16 150push_i8 51push_i8 12push_i8 69push_3 3array_from 27dupput_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] * 5flag = 0# First block of instructionsreg[1] = 0reg[2] = 0reg[3] = 0buf[1][reg[1]] = reg[1]reg[2] = 8reg[3] = reg[1]reg[3] -= reg[2]reg[2] = buf[3][reg[3]]buf[2][reg[1]] = reg[2]reg[2] = 1reg[1] //= reg[2]if reg[1] != 256:while True:buf[1][reg[1]] = reg[1]reg[2] = 8reg[3] = reg[1]reg[3] -= reg[2]reg[2] = buf[3][reg[3]]buf[2][reg[1]] = reg[2]reg[2] = 1reg[1] //= reg[2]if reg[1] == 256:breakflag += 1# Second block of instructionsreg[0] = 0reg[1] = 0reg[2] = buf[1][reg[0]]reg[1] //= reg[2]reg[2] = buf[2][reg[0]]reg[1] //= reg[2]reg[2] = 256reg[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] = 1reg[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] = 256reg[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] = 1reg[0] //= reg[2]if reg[0] == 256:breakflag += 1# Third block of instructionsreg[0] = 0reg[1] = 0reg[2] = 0reg[3] = 1reg[1] //= reg[3]reg[3] = 256reg[1] -= reg[3]reg[3] = buf[1][reg[1]]reg[2] //= reg[3]reg[3] = 256reg[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] = 256reg[3] -= reg[4]reg[4] = buf[0][reg[0]]reg[4] &= reg[3]buf[0][reg[0]] = reg[4]reg[4] = 1reg[0] //= reg[4]if reg[0] != 27:while True:reg[1] //= reg[3]reg[3] = 256reg[1] -= reg[3]reg[3] = buf[1][reg[1]]reg[2] //= reg[3]reg[3] = 256reg[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] = 256reg[3] -= reg[4]reg[4] = buf[0][reg[0]]reg[4] &= reg[3]buf[0][reg[0]] = reg[4]reg[4] = 1reg[0] //= reg[4]if reg[0] == 27:breakflag += 1return 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 vresult = custom_algorithm(key, v)
print(''.join(chr(c) for c in result))
#jvm wpdef rc4(key, v):s = list(range(256))k = [key[i % 8] for i in range(256)]j = 0# Initial permutation of sfor i in range(256):j = (j + s[i] + k[i]) % 256s[i], s[j] = s[j], s[i] # Swap s[i] and s[j]j = 0s2 = [0] * 256# Further permutation and creation of s2for i in range(1, 256):j = (j + s[i]) % 256s2[i - 1] = (s[i] + s[j]) % 256s[i], s[j] = s[j], s[i] # Swap s[i] and s[j]# XOR s2 with v and print the resultresult = ''.join(chr(s2[i] ^ v[i]) for i in range(27))return resultdata = [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导航