【Python逆向】深入Pyd逆向

news/2024/12/21 11:24:40/文章来源:https://www.cnblogs.com/o-O-oO/p/18620575

pyd 文件是编译生成的 Python 扩展模块,是类似 so、dll 的一种 Python 文件。
pyd 文件无法像 pyc文件那样恢复源码,只能通过逆向手段去恢复逻辑。

一、理解pyd文件

1.1 编译pyd

自己编译一个 pyd 保留符号来看。

test.py

import base64
key = [ord(i) for i in "key"]
res = "GVhilbQktqU="
def check(flag):if len(flag) != 16:return Falseflag = int(flag, 16)flag = flag.to_bytes(8, 'big')flag = encrypt(flag, key)flag = base64.b64encode(bytes(flag)).decode()if flag == res:return Truereturn False
def encrypt(ptext, key):S = list(range(256))j = 0out = []for i in range(256):j = (j + S[i] + key[i % len(key)]) % 256S[i], S[j] = S[j], S[i]i = j = 0for t in ptext:i = (i + 1) % 256j = (j + S[i]) % 256S[i], S[j] = S[j], S[i]out.append(t ^ S[(S[i] + S[j]) % 256])return out
def logic():flag = input("Enter flag: ")if check(flag):print("Correct flag!")else:print("Wrong flag!")
__test__ = {}

setup.py

from setuptools import setup, Extension
from Cython.Build import cythonize
ext_modules = [Extension(name = "test",sources = ["test.py"],extra_compile_args = ["/Zi"],extra_link_args = ["/DEBUG"])
]
setup(name = "test",ext_modules = cythonize(ext_modules, annotate=True),
)

编译:

python .\setup.py build_ext --inplace

在当前目录就会生成 pyd 和对应的 pcb。

二、分析pyd

2.1 全局变量与常量

在分析 pyd 逻辑之前,需要关注这几个函数(全局变量相关):

1、__Pyx_CreateStringTabAndInitStrings
2、__Pyx_InitCachedBuiltins
3、__Pyx_InitCachedConstants
4、__Pyx_InitConstants
5、__Pyx_InitGlobals
6、PyInit_test

这些函数会设置一些全局变量、常量在 _pyx_mstate_global。

__Pyx_CreateStringTabAndInitStrings

这里设置了字符串:

1、程序逻辑本身的字符串;
2、变量名;
3、模块属性;

一般特征为 _pyx_mstate_global ->__pyx_n_s_ + 字符串 为获取目标字符串。
通过其实现字符串的使用、变量的获取、属性的获取。
__Pyx_InitCachedBuiltins

这里获取了程序逻辑会用到的 python 自带的函数:

v6 = _Pyx_PyObject_GetAttrStrNoError(_pyx_mstate_global->__pyx_b, pyx_n_s_input);
_pyx_builtin_input = v6;

__Pyx_InitConstants

设置一些常数,程序要使用时直接 _pyx_mstate_global->__pyx_int_value

v0 = (_object *)PyLong_FromLong(0LL);
_pyx_mstate_global->__pyx_int_0 = v0;
v1 = (_object *)PyLong_FromLong(1LL);
_pyx_mstate_global->__pyx_int_1 = v1;
v2 = (_object *)PyLong_FromLong(8LL);
_pyx_mstate_global->__pyx_int_8 = v2;

__Pyx_InitCachedConstants

同样设置了一些常数,但更多的好像是 tuple,方便了函数传参。

v0 = (_object *)PyTuple_Pack(2LL, _pyx_mstate_global->__pyx_int_8, _pyx_mstate_global->__pyx_n_s_big);
_pyx_mstate_global->__pyx_tuple_ = v0;

PyInit_test

通过一路跳转找到 __pyx_pymod_exec_test


这里会进行一些初始化(库的导入、全局变量初始化...)。
_pyx_mstate_global->__pyx_d 创建了一个空的字典,以便全局变量的读取:

Dict = PyModule_GetDict();
_pyx_mstate_global->__pyx_d = (_object *)Dict;

一些常量的设置:

v26 = (_object *)PyLong_FromLong(256LL)
v27 = _pyx_mstate_global
_pyx_mstate_global->__pyx_int_256 = v26

设置 builtins 的一些 python 自带函数:

v7 = (_object *)PyImport_AddModule("builtins");
_pyx_mstate_global->__pyx_b = v7;
pyx_n_s_input = _pyx_mstate_global->__pyx_n_s_input;
_pyx_builtin_input = v33;

导入 base64 库:

pyx_n_s_base64 = _pyx_mstate_global->__pyx_n_s_base64;
Module = (_object *)PyImport_GetModule(pyx_n_s_base64);
p_ob_refcnt = &Module->ob_refcnt;
PyDict_SetItem(_pyx_mstate_global->__pyx_d, _pyx_mstate_global->__pyx_n_s_base64, p_ob_refcnt)

生成 key 的操作:key = [ord(i) for i in "key"]

p_ob_refcnt = (_QWORD *)PyList_New(0LL);
Iter = PyObject_GetIter(_pyx_mstate_global->__pyx_n_s_key);
v2 = (_QWORD *)Iter;
v46 = *(__int64 (__fastcall **)(_QWORD *))(*(_QWORD *)(Iter + 8) + 224LL);
while (1) {v47 = (_object *)v46(v2);v3 = v47;if ( !v47 )break;v50 = _pyx_7genexpr__pyx_v_4test_i;v51 = v47;_pyx_7genexpr__pyx_v_4test_i = v47;ob_refcnt_low = LOBYTE(v51[2].ob_refcnt);v59 = (_object *)PyLong_FromLong(ob_refcnt_low);PyList_Append(p_ob_refcnt, v59);
}
PyDict_SetItem(_pyx_mstate_global->__pyx_d, _pyx_mstate_global->__pyx_n_s_key, p_ob_refcnt);

设置 res = "GVhilbQktqU="

PyDict_SetItem(_pyx_mstate_global->__pyx_d,_pyx_mstate_global->__pyx_n_s_res,_pyx_mstate_global->__pyx_kp_s_GVhilbQktqU
)

设置 check 函数:

v66 = _Pyx_CyFunction_New(&_pyx_mdef_4test_1check,v64,_pyx_mstate_global->__pyx_n_s_check,v65,_pyx_mstate_global->__pyx_n_s_test,_pyx_mstate_global->__pyx_d,_pyx_mstate_global->__pyx_codeobj__8
);
PyDict_SetItem(_pyx_mstate_global->__pyx_d, _pyx_mstate_global->__pyx_n_s_check, v66)

通过 _pyx_mdef_4test_1check找到 _pyx_pw_4test_1check

_pyx_pw_4test_1check 会调用 _pyx_pf_4test_check

_pyx_pf_4test_check 是 check 的函数逻辑。

分析逻辑

通过上面的铺垫,现在开始分析一下测试的三个函数。
logic:

通过以下三个函数的片段可知,程序逻辑:flag = input("Enter flag: ")

_Pyx_CreateStringTabAndInitStrings:
__pyx_string_tab[1].p = &_pyx_mstate_global->__pyx_kp_s_Enter_flag;
__pyx_string_tab[1].s = "Enter flag: ";
_Pyx_InitCachedConstants:
v6 = (_object *)PyTuple_Pack(1LL, v5->__pyx_kp_s_Enter_flag, v4);
v8 = _pyx_mstate_global;
_pyx_mstate_global->__pyx_tuple__3 = v6;
_pyx_pf_4test_4logic:
v5 = _Pyx_PyObject_Call(_pyx_builtin_input, _pyx_mstate_global->__pyx_tuple__3, a3);

执行调用 check(flag):

pyx_n_s_check = _pyx_mstate_global->__pyx_n_s_check;
AttrStrNoError = (_object *)_PyDict_GetItem_KnownHash(_pyx_mstate_global->__pyx_d,pyx_n_s_check,pyx_n_s_check[1].ob_type
);
v13 = _pyx_mstate_global->__pyx_d;
__pyx_callargs[1] = v6;
v20 = _Pyx_PyObject_FastCallDict(AttrStrNoError, &__pyx_callargs[-v16 + 1], (unsigned int)(v16 + 1), pyx_d);

判断 check 结果:

if check(flag):print("Correct flag!")else:print("Wrong flag!")
IsTrue = v20 == (_object *)_Py_TrueStruct;
if ( IsTrue )
{v24 = _Pyx_PyObject_Call(_pyx_builtin_print, _pyx_mstate_global->__pyx_tuple__4, v21);
}
else
{v24 = _Pyx_PyObject_Call(_pyx_builtin_print, _pyx_mstate_global->__pyx_tuple__5, v21);
}

check:

if len(flag) != 16: return False
_object *__fastcall _pyx_pf_4test_check(_object *__pyx_v_flag, _object *__pyx_self) {v3 = PyObject_Size(__pyx_self);if ( v3 != 16 )goto LABEL_4;...
}
flag = int(flag, 16):
v8 = (_object *)PyTuple_New(2LL, v4);
++v2->ob_refcnt;
v11 = _pyx_mstate_global;
v8[1].ob_type = (_typeobject *)v2;
++v11->__pyx_int_16->ob_refcnt;
v8[2].ob_refcnt = (__int64)v11->__pyx_int_16;
v12 = _Pyx_PyObject_Call(PyLong_Type, v8, v9);
flag = flag.to_bytes(8, 'big'):
_Pyx_InitCachedConstants:
v0 = (_object *)PyTuple_Pack(2LL, _pyx_mstate_global->__pyx_int_8, _pyx_mstate_global->__pyx_n_s_big);
_pyx_mstate_global->__pyx_tuple_ = v0;
_pyx_pf_4test_check:
Attr = (_object *)PyObject_GetAttr(v12, pyx_n_s_to_bytes);
v19 = _Pyx_PyObject_Call(Attr, _pyx_mstate_global->__pyx_tuple_, v18);
flag = encrypt(flag, key):
v24 = _pyx_mstate_global->__pyx_n_s_encrypt;
Item_KnownHash = (_object *)_PyDict_GetItem_KnownHash(_pyx_mstate_global->__pyx_d, v24, v24[1].ob_type);
AttrStrNoError = Item_KnownHash;
v30 = v21->__pyx_n_s_key;
BuiltinName = (_object *)_PyDict_GetItem_KnownHash(v21->__pyx_d, v30, v30[1].ob_type);
pyx_d = _pyx_mstate_global->__pyx_d;
_pyx_dict_version = (unsigned __int64)_pyx_mstate_global->__pyx_d[1].ob_type;
_pyx_dict_cached_value = BuiltinName;
v33 = 0;
__pyx_callargs[0] = p_ob_base;
__pyx_callargs[1] = v19;
__pyx_callargs[2] = BuiltinName;
v36 = _Pyx_PyObject_FastCallDict(AttrStrNoError, &__pyx_callargs[-v33 + 1], (unsigned int)(v33 + 2), v20);
flag = base64.b64encode(bytes(flag)).decode():
v42 = _pyx_mstate_global->__pyx_n_s_base64;
v43 = (_object *)_PyDict_GetItem_KnownHash(_pyx_mstate_global->__pyx_d, v42, v42[1].ob_type);
AttrStrNoError = v43;
pyx_n_s_b64encode = v39->__pyx_n_s_b64encode;v47 = PyObject_GetAttr(AttrStrNoError, pyx_n_s_b64encode);
v49 = (_object *)v47;
v52 = 0LL;
v53 = 0;
args[1] = v52;
v74 = v50;
AttrStrNoError = _Pyx_PyObject_FastCallDict(v49, &__pyx_callargs[-v53 - 1], (unsigned int)(v53 + 1), v51);
pyx_n_s_decode = _pyx_mstate_global->__pyx_n_s_decode;
v58 = PyObject_GetAttr(AttrStrNoError, pyx_n_s_decode);
v49 = (_object *)v58;
v65 = _Pyx_PyObject_FastCallDict(v49, &args[-v61], v62, v59);
if flag == res: return True
else: return False
v2 = v65;
v69 = _pyx_mstate_global->__pyx_n_s_res;
AttrStrNoError = (_object *)_PyDict_GetItem_KnownHash(_pyx_mstate_global->__pyx_d, v69, v69[1].ob_type);
v49 = (_object *)PyObject_RichCompare(v2, AttrStrNoError, 2LL);
IsTrue = _Pyx_PyObject_IsTrue(v49);
if ( !IsTrue )
{LABEL_4:v5 = ++_Py_FalseStruct;goto LABEL_157;
}
v5 = ++_Py_TrueStruct;
LABEL_157:
return (_object *)v5;

encrypt:

S = list(range(256)):
v9 = _Pyx_PyObject_Call(_pyx_builtin_range, _pyx_mstate_global->__pyx_tuple__2, __pyx_self
);
pyx_int_1 = (_object *)PySequence_List(v9);
j = 0
out = []
for i in range(256):j = (j + S[i] + key[i % len(key)]) % 256S[i], S[j] = S[j], S[i]v13 = pyx_int_1;
obj = pyx_int_1;
pyx_int_0 = v16->__pyx_int_0;
v17 = PyList_New(0LL);
v64 = (_QWORD *)v17;
for ( i = 0; i < 256; ++i )
{v19 = PyLong_FromLong((unsigned int)i);v20 = (_object *)v19;v6 = v19;Item = _Pyx_PyObject_GetItem(v13, v20);pyx_int_1 = Item;v9 = (_object *)PyNumber_Add(pyx_int_0, Item);v23 = PyObject_Size(__pyx_self);v24 = PyLong_FromSsize_t(v23);pyx_int_1 = (_object *)v24;v4 = (_object *)PyNumber_Remainder(v6, v24);pyx_int_1 = _Pyx_PyObject_GetItem(__pyx_self, v4);v4 = (_object *)PyNumber_Add(v9, pyx_int_1);v27 = _Pyx_PyInt_RemainderObjC(v4, _pyx_mstate_global->__pyx_int_256, v25, v26, v61);pyx_int_1 = _Pyx_PyObject_GetItem(obj, v27);v4 = _Pyx_PyObject_GetItem(obj, (_object *)v6);PyObject_SetItem(obj, v6, pyx_int_1);PyObject_SetItem(obj, pyx_int_0, v4);
}
for t in ptext:i = (i + 1) % 256j = (j + S[i]) % 256S[i], S[j] = S[j], S[i]out.append(t ^ S[(S[i] + S[j]) % 256])
v32 = _pyx_mstate_global;
v33 = (_QWORD *)v6;
v6 = (__int64)v32->__pyx_int_0;
v34 = _pyx_mstate_global;
v35 = v34->__pyx_int_0;
Iter = PyObject_GetIter(__pyx_v_key);
v39 = *(__int64 (__fastcall **)(_QWORD))(*(_QWORD *)(Iter + 8) + 224LL);
v66 = v39;
while ( 2 ) {if ( !v39 ) {pyx_int_1 = _pyx_mstate_global->__pyx_int_1;v44 = *(_object **)(v6 + 8);v48 = _Pyx_PyInt_RemainderObjC(pyx_int_1, _pyx_mstate_global->__pyx_int_256, v30, v31, v61);v50 = _Pyx_PyObject_GetItem(obj, v48);pyx_int_1 = (_object *)PyNumber_Add(pyx_int_0, v50);v53 = _Pyx_PyInt_RemainderObjC(pyx_int_1, _pyx_mstate_global->__pyx_int_256, v51, v52, v62);pyx_int_0 = v53;v55 = v53;v9 = _Pyx_PyObject_GetItem(obj, v53);pyx_int_1 = _Pyx_PyObject_GetItem(obj, (_object *)v6);PyObject_SetItem(obj, v6, v9);PyObject_SetItem(obj, v55, pyx_int_1);pyx_int_1 = _Pyx_PyObject_GetItem(obj, (_object *)v6);v56 = _Pyx_PyObject_GetItem(obj, v55);v5 = (_object *)PyNumber_Add(pyx_int_1, v56);v9 = _Pyx_PyInt_RemainderObjC(v5, _pyx_mstate_global->__pyx_int_256, v57, v58, v63);v5 = _Pyx_PyObject_GetItem(obj, v9);v9 = (_object *)PyNumber_Xor(v65, v5);PyList_Append(v64, v9);}
}

实践分析

这里用 ciscb ccb 比赛的 Cython 题目进行实践。
exe 解包后,反编译 pyc 得到源码:

import ez
flag = input()
flag1 = list(flag)
value = []
b = 0
ck = 0
if len(flag1) == 24:for i in range(0, len(flag1), 4):b = (ord(flag1[i]) << 16) | (ord(flag1[i + 1]) << 8) | ord(flag1[i + 2]) | ord(flag1[i + 3])value.append(b)key = [102, 108, 97, 103]flag_encrypt = []for i in range(0, 6, 2):print(f"{value[i]:x} {value[i + 1]:x}")res = ez.encrypt(value[i], value[i + 1], key)flag_encrypt.append(res)ck = ez.check(flag_encrypt)if ck == 3:print('yes!!!,you get right flag')else:print('wrong!!!')
else:print('wrong!!!')

主要逻辑在 ez.pyd,但这加密方式一眼 tea。
bindiff 用 test.pyd恢复符号,对着看去分析。
根据 ez.encrypt 字符串来找引用函数,一般是第二个。
分析代码如下(省略一些不影响逻辑分析的):

__int64 __fastcall _pyx_pf_4test_2encrypt(__int64 a1, __int64 arg_v0, __int64 arg_v1, __int64 arg_key
){v12 = pyx_mstate_global->__pyx_n_s_c_uint32_; // c_uint32AttrStrNoError = (_QWORD *)PyDict_GetItem_KnownHash(pyx_mstate_global->__pyx_d, v12, v12[1].ob_type);v13 = 0;v102[0] = arg_v0;BuiltinName = (_QWORD *)_Pyx_PyObject_FastCallDict((__int64)AttrStrNoError, &v102[-v13], (unsigned int)(v13 + 1));v21 = pyx_mstate_global->__pyx_n_s_c_uint32_;Item_KnownHash = (_QWORD *)PyDict_GetItem_KnownHash(pyx_mstate_global->__pyx_d, v21, v21[1].ob_type);v102[1] = Item;v103[0] = arg_v1;AttrStrNoError = (_QWORD *)_Pyx_PyObject_FastCallDict((__int64)Item_KnownHash, &v103[-v22], (unsigned int)(v22 + 1));v29 = v25->__pyx_n_s_c_uint32_;v30 = (_QWORD *)PyDict_GetItem_KnownHash(v25->__pyx_d, v29, v29[1].ob_type);v25 = pyx_mstate_global;BuiltinName = v30;pyx_int_0 = v25->__pyx_int_0;v103[1] = (__int64)v31;v101 = _Pyx_PyObject_FastCallDict((__int64)BuiltinName, &pyx_int_0 - v32, v32 + 1);v35 = (_QWORD *)v101;AttrStrNoError = (_QWORD *)v101;v99 = pyx_int_1415865428;v105 = 0;v18 = 11;do{pyx_n_s_value = pyx_mstate_global->__pyx_n_s_value;Attr = PyObject_GetAttr(Item_KnownHash, pyx_n_s_value);AttrStrNoError = (_QWORD *)Attr;v42 = pyx_mstate_global->__pyx_n_s_value;v44 = PyObject_GetAttr(v26, v42);BuiltinName = (_QWORD *)v44;Item_KnownHash = (_QWORD *)_Pyx_PyInt_LshiftObjC(v44, pyx_mstate_global->__pyx_int_value_3);v45 = pyx_mstate_global->__pyx_n_s_value;v46 = *(__int64 (__fastcall **)(_QWORD *, _object *))(v26[1] + 144i64);v47 = PyObject_GetAttr(v26, v45);BuiltinName = (_QWORD *)v47;Item = _Pyx_PyInt_RshiftObjC(v47, pyx_mstate_global->__pyx_int_value_6, 6i64);BuiltinName = (_QWORD *)PyNumber_Xor(Item_KnownHash, Item);v48 = pyx_mstate_global->__pyx_n_s_value;v49 = *(__int64 (__fastcall **)(_QWORD *, _object *))(v26[1] + 144i64);v50 = PyObject_GetAttr(v26, v48);Item = v50;Item_KnownHash = (_QWORD *)PyNumber_Add(BuiltinName, v50);v51 = pyx_mstate_global->__pyx_n_s_value;v53 = PyObject_GetAttr(v101, v51);v54 = pyx_mstate_global->__pyx_n_s_value;v56 = PyObject_GetAttr(v101, v54);v58 = PyNumber_And(v56, pyx_mstate_global->__pyx_int_value_3);v5 = (_QWORD *)v58;BuiltinName = (_QWORD *)_Pyx_PyObject_GetItem(arg_key, v5);v5 = (_QWORD *)PyNumber_Add(Item, BuiltinName);BuiltinName = (_QWORD *)PyNumber_Xor(Item_KnownHash, v5);v5 = (_QWORD *)PyNumber_InPlaceAdd(AttrStrNoError, BuiltinName);v59 = pyx_mstate_global->__pyx_n_s_value;v61 = PyObject_SetAttr(v98, v59, v5);v62 = pyx_mstate_global->__pyx_n_s_value;v64 = PyObject_GetAttr(v101, v62);BuiltinName = (_QWORD *)PyNumber_InPlaceAdd(v64, v99);v67 = PyObject_SetAttr(v101, v65, BuiltinName);v68 = pyx_mstate_global->__pyx_n_s_value;v70 = PyObject_GetAttr(v26, v68);BuiltinName = (_QWORD *)v70;v71 = pyx_mstate_global->__pyx_n_s_value;v73 = PyObject_GetAttr(v98, v71);AttrStrNoError = (_QWORD *)_Pyx_PyInt_LshiftObjC(v73, pyx_mstate_global->__pyx_int_value_3);v74 = pyx_mstate_global->__pyx_n_s_value;v76 = PyObject_GetAttr(v98, v74);Item_KnownHash = (_QWORD *)_Pyx_PyInt_RshiftObjC(v76, pyx_mstate_global->__pyx_int_value_6, 6i64);v5 = (_QWORD *)PyNumber_Xor(AttrStrNoError, Item_KnownHash);v77 = pyx_mstate_global->__pyx_n_s_value;v79 = PyObject_GetAttr(v98, v77);Item_KnownHash = (_QWORD *)v79;AttrStrNoError = (_QWORD *)PyNumber_Add(v5, v79);v80 = pyx_mstate_global->__pyx_n_s_value;v82 = PyObject_GetAttr(v101, v80);Item_KnownHash = (_QWORD *)v82;v83 = pyx_mstate_global->__pyx_n_s_value;v85 = PyObject_GetAttr(v101, v83);Item = _Pyx_PyInt_RshiftObjC(v85, pyx_mstate_global->__pyx_int_4, 11i64);v87 = PyNumber_And(Item, pyx_mstate_global->__pyx_int_value_3);Item = _Pyx_PyObject_GetItem(arg_key, v5);v5 = (_QWORD *)PyNumber_Add(Item_KnownHash, Item);Item = PyNumber_Xor(AttrStrNoError, v5);v5 = (_QWORD *)PyNumber_InPlaceAdd(BuiltinName, Item);v88 = pyx_mstate_global->__pyx_n_s_value;v90 = PyObject_SetAttr(v26, v88, v5);Item_KnownHash = v98;++v105;}while ( v105 < 64 );v91 = pyx_mstate_global->__pyx_n_s_value;v93 = PyObject_GetAttr(v98, v91);v94 = pyx_mstate_global->__pyx_n_s_value;v96 = PyObject_GetAttr(v26, v94);Item = v96;v97 = PyTuple_New(2i64);*(_QWORD *)(v97 + 24) = v5;*(_QWORD *)(v97 + 32) = Item;return v37;
}

还原 python 代码:

def encrypt(v0, v1, key):v0 = ctypes.c_uint32(v0)v1 = ctypes.c_uint32(v1)num = ctypes.c_uint32(0)for i in range(64):t1 = v1.value + (v1.value  << 3 ^ v1.value >> 6)t2 = num.value + key[num.value & 3]t3 = t1 ^ t2v0.value = v0.value + t3num.value = num.value + 1415865428t1 = v0.value + (v0.value << 3 ^ v0.value >> 6)t2 = num.value + key[num.value >> 11 & 3]t3 = t1 ^ t2v1.value = v1.value + t3return v0.value, v1.value

还有一个 ez.check,直接使用了 ez.data 与加密结果进行比较。
因此直接解密:

def decrypt(v0, v1, key):num = 0delta = 0x54646454for i in range(64):num += deltanum = num & 0xFFFFFFFFfor i in range(64):t1 = (v0 + ((v0 << 3) ^ (v0 >> 6))) & 0xFFFFFFFFt2 = (num + key[(num >> 11) & 3]) & 0xFFFFFFFFt3 = t1 ^ t2v1 = v1 - t3v1 &= 0xFFFFFFFFnum = num - deltanum = num & 0xFFFFFFFFt1 = (v1 + ((v1 << 3) ^ (v1 >> 6))) & 0xFFFFFFFFt2 = (num + key[num & 3]) & 0xFFFFFFFFt3 = t1 ^ t2v0 = v0 - t3v0 &= 0xFFFFFFFFreturn v0, v1
key = [102, 108, 97, 103]
result = [2129084917, 4147024244, 2971480309, 1606961219, 710575902, 4012634395]
flag = []
for i in range(3):v0, v1 = result[i * 2], result[i * 2 + 1]flag += decrypt(v0, v1, key)
flag_str = ""
for i in flag:flag_str += i.to_bytes(4, "big").decode()
print(flag_str)

来源

https://xz.aliyun.com/t/16800?time__1311=Gui%3DGIfG7KGNDQUPBK0Q5SbctcED

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React之Json编辑器

我们先看下效果,这个白色是不是非常不错?没有太多复杂的功能,就是当一个简洁显示json并且进行编辑的功能接下来是代码部分 import AceEditor from react-ace; import { Button, Modal } from antd; import ./styles.css;// Import ace editor themes and modes import ace-b…

2024 ASP.NET Core 开发者路线图

2024 ASP.NET Core 开发者路线图

OCR实践—PaddleOCR

有个项目需求,对拍摄的问卷图片,进行自动得分统计【得分是在相应的分数下面打对号】,输出到excel文件 原始问卷文件见下图,真实的图片因使用手机拍摄的图片,存在一定的畸变,技术调研 传统方法 传统方法,通过线检测 先对 表格进行矫正【仿射变换】,然后二次线检测 划分出…

Google发布了它所称的“推理”AI模型

Google发布了它所称的“推理”AI模型——但这还处于实验阶段,根据我们简短的测试,显然仍有改进空间。 这个新模型名为Gemini 2.0 Flash Thinking Experimental(名字有点长,确实),可以在Google的AI原型平台AI Studio中使用。模型卡片描述它是“最适合多模态理解、推理和编…

【Python GUI 编程】tkinter :Ttk 组合框 Combobox

在本文中,将介绍如何创建一个 tkinter Combobox 组合框小部件,该小部件允许用户从一组值中选择一个值。 Combobox 组合框小部件是新增的 Ttk 主题小部件,是 Entry 文本框和 Listbox 列表框的组合。除了允许在一组值中选择一个值外,它还允许输入自定义值。 创建组合框 要创建…

【Python GUI 编程】tkinter:Ttk 选项卡 Notebook

在本文中,将介绍如何使用 Tkinter Notebook 小部件创建选项卡。 Notebook 是由 Tkinter Ttk 模块引入的强大小部件。允许开发者创建包含多个选项卡的界面,每个选项卡可以包含不同的内容。 创建 Notebook 小部件,请使用如下构造函数: notebook = ttk.Notebook(master,**kw)添…

在虚拟机里执行protoc报非法指令( Illegal instruction)

问题 在x86虚拟机里编译perfetto的时候遇到执行protoc报非法指令,但是在host上编译的时候并没有这样的问题 原因 虽然虚拟机和宿主机都是同一个指令集架构,但是CPU在一些特殊指令上的支持还是有区别的,如果Host可以,但是虚拟机上不行,可能就是虚拟机CPU不支持某些特性,导…

中考阅读理解深入逻辑分析-001 A Dine to Remember 难忘的一餐

中考阅读理解深入逻辑分析-001 A Dine to Remember 难忘的一餐 文章正文 It was a few years ago. A friend had sent me a restaurant gift card for Christmas and I had picked a sunny Sunday afternoon to use it. It felt good taking my two grown sons and daughter to…

HTTP协议及安全防范

HTTP(Hypertext Transfer Protocol)超文本传输协议是一个用于 Web 应用程序通信的应用层协议。它是一种客户端-服务器协议,客户端通过发送请求到服务器来获取资源,服务器则根据请求返回响应。HTTP 协议通常使用 TCP作为传输协议,但也可以使用其它传输协议 由于图片解析问题…

LDA主题模型——原理和模型(二)

img { display: block; margin-left: auto; margin-right: auto } table { margin-left: auto; margin-right: auto } 主题模型是用于发现文档集合中隐含主题的统计模型,主题可以定义为“文档集中具有相同词境的词的集合模式”。主题模型克服了传统信息检索中文档相似度计算方…

LDA主题模型——贝叶斯分布与其共轭(一)

img { display: block; margin-left: auto; margin-right: auto } table { margin-left: auto; margin-right: auto } 贝叶斯分布理论是统计推断的重要分支,其核心思想是利用贝叶斯定理,将先验知识与新观测数据结合,从而动态更新对未知参数的认识。这一理论框架以概率为基础…