某app c++层3处魔改md5详解

news2024/10/5 19:20:02

hello everybody,本期是安卓逆向so层魔改md5教学,干货满满,可以细细品味,重点介绍的是so层魔改md5的处理.

常见的魔改md5有:

        1:明文加密前处理 2:改初始化魔数 3:改k表中的值 4:改循环左移的次数  本期遇到的是124.且循环左移的次数是动态的,需要前面的加密结果处理生成

目录

首先介绍md5的实现

说明:

登陆抓包:

sign的加密

总结:

首先介绍md5的实现

1首先对明文16进制编码,比如我的名字 杨如画 会被编码成 e6 9d a8 e5 a6 82 e7 94 bb

2把明文填充到448bit(比如e6是两个16进制字符,也就是一个字节,8bit),填充方式是先填充一个80,接着一直填充00 00 00直到448bit,

填充成这样e6 9d a8 e5 a6 82 e7 94 bb 80 00 00 00...(56个字节,448bit)

3附加消息长度,需要填充8个字节,也就是e6 9d a8 e5 a6 82 e7 94 bb的长度9个字节,72位,长度就是72,转成16进制就是48,理论上填充的长度为48 也就是

00 00 00 00 00 00 00 48,但是md5处理的时候需要把这8个字节转为小端序,什么是小端续呢?你可以上网查,我简单说一下这里的小端序就是把这8个字节,注意是以字节为单位把最后一个放到第一个,倒数第二个放到第二个,以此类推,最终结果是48 00 00 00 00 00 00 00.  md5的输入长度是无限长的,如果64bit位放不下,也就是长度大于2的64次方的话,会取低64bit,也是按照小端序来取的.  此外sha3算法也是明文无限长,其他hash算法不是.

4最终明文处理成e6 9d a8 e5 a6 82 e7 94 bb 80 00 00 00...48 00 00 00 00 00 00 00,一共512bit,如果输入的数据刚好为448bit,那么就需要填充512bit,再加上附加消息长度64bit,一共1024bit,因为md5的分组长度为512bit,所以需要进行分组处理

至于k表和初始化魔数和循环左移我们待会再说,先对md5的明文处理有一个概念,注意这很重要,后续需要用到.

概念介绍完了,我们来实战吧

说明:

设备: pixel4 XL android10

抓包:charles配合socksdroid

下载地址:aHR0cHM6Ly93d3cud2FuZG91amlhLmNvbS9hcHBzLzMwNjM5OS9oaXN0b3J5X3YzNjA=

frida版本:16.0.1

此版本是旧版本,新版本算法并没有改,流程也大致差不多,复杂的话可以frida trace,后续也会介绍到,事实上这也是我为了逆这个算法现学的,介绍一下背景,我是学了frida rpc接触到了这个app,当时逆登陆的时候有个sign,当时用的是rpc,因为rpc需要开着手机,我想着能不能逆向出完整的算法呢?这期间遇到了非常大的挑战,因为很多frida的api我也不太熟悉,我也是现学现用,后续会一一介绍,整个魔改md5耗时3天.

登陆抓包:

1 查询参数没什么特别的,重点看表单,username是手机号,密码加密了,还有一个用作验签的sign,这个sign的作用我之前说过很多次了,他是用来验签的,通常是把查询参数或者表单中的参数除sign之外的其他值拼接起来加密,防止数据包被恶意篡改,当然也不是不能篡改,把这个sign逆了不就行了吗

2 password的我就不说了,在java层,我直接给出代码吧  定位可以搜字符串,hook java层系统函数等等

# 128位密钥
_str = hashlib.md5('16751641924'.encode('utf-8')).hexdigest()
key = _str[0:16].encode('utf-8')

# 128位IV(Initialization Vector)
iv = 'yoloho_dayima!%_'.encode('utf-8')

# 明文
plaintext = "1472580369Xx"  # 不能超过31个字符
# 加密
cipher = AES.new(key, AES.MODE_CBC, iv)
padded_data = pad(plaintext.encode(), AES.block_size)
ciphertext = cipher.encrypt(padded_data)

# 将密文以Base64格式输出
password = base64.b64encode(ciphertext).decode()
print(password)

sign的加密

3 定位我也不说了,搜字符串,hook什么hashmap,hashset,stringbuilder之类的你都试试吧,总能找到的,我就贴下面了

4 hook encrypt_data这个native函数,返回的就是sign,直接右键复制为frida片段

5 有java的api 要包在Java.perform里 

Java.perform(function (){
    let Crypt = Java.use("com.yoloho.libcore.util.Crypt");
Crypt["encrypt_data"].implementation = function (j, str, j2) {
    console.log(`Crypt.encrypt_data is called: j=${j}, str=${str}, j2=${j2}`);
    let result = this["encrypt_data"](j, str, j2);
    console.log(`Crypt.encrypt_data result=${result}`);
    return result;
};
})

6 配合着抓包,点击一下登陆,发现加密的结果与抓包中一样,那铁定是这里了

7 接下来为了避免一直手点登陆,可以进行java层主动调用

function call(){
    Java.perform(function (){
    let Crypt = Java.use("com.yoloho.libcore.util.Crypt");
var res = Crypt["encrypt_data"](0, '23eedd78b2b95ef16b82da4fe2177bdcb1920dd6user/login16751641924oKc0ZztEbNCIcDKL3hoF/A==', 85)
    console.log(res);
})
}

8 我建议你采用我这个主动调用,这样最终加密出来的结果会和我的一样,方便你调试

9 接下来我们把libCrypt.so拖到ida32中反编译,Crypt名字在上面的java代码中出现了,只有32位的所以拖到ida32中

10 反编译后搜一下java发现是静态注册,这里名字叫encrypt_1data是因为进行了符号修饰

11 这里直接点进去看内部逻辑

12 转换一下JNIEnv对象,ida7.5以后可以不用导头文件,直接改类型

13 看到NewStringUTF,第一个参数是JNIEnv,第二个参数是CString,这里是把CString转为JString再返回给java层,所以最终加密的结果就是v12

14 这里可以hook 1B88这个函数,这种没有名字的通常后面就是偏移量,不放心的话可以点进去看看,加上so基值就可以得到函数内存地址了,这是arm指令的,如果是thubm指令的就得+1,如果你不会看arm还是thumb指令就看so是32还是64,32的一般是thumb,64的一般是arm指令

15 接下来hook sub_1B88这个函数,这是修改过后的,一开始你不知道哪些是地址就把所有参数打印一遍,是地址再dump,因为你dump数字的话是会报错的

var soAddr = Module.findBaseAddress("libCrypt.so");
var funcAddr = soAddr.add(0x1B88+1)  //32位+1

Interceptor.attach(funcAddr,{
            onEnter: function(args){
                console.log('onEnter arg[0]: ',args[0])
                console.log('onEnter arg[1]: ',args[1])
                console.log('onEnter arg[2]: ',hexdump(args[2]))
                console.log('onEnter arg[3]: ',args[3])
                console.log('onEnter arg[4]: ',args[4])
                console.log('onEnter arg[5]: ',args[5])
                console.log('onEnter arg[6]: ',args[6])
                this.arg2 = args[2]
                this.arg6 = args[6]
            },
            onLeave: function(retval){
                console.log('onLeave arg[2]: ',hexdump(this.arg2))
                console.log('onLeave arg[6]: ',hexdump(this.arg6))
                console.log('onLeave result: ',retval)

            }
        });

16这里开着两个hook脚本,java层主动调用,分析so的结果,后面这张图我就不贴了,就是java层的主动调用

17 我们可以看到结果在arg6中,也就是第7个参数,证明结果确实来自v12

18 而arg2就是我们从java层传进的第二个明文参数,只有这个是重要的,其他不重要的就不要输出,影响判断 

19 接下来我们从1B88点进去看看,点进去后发现这里面调用了很多函数,我是把这些函数都hook了一般,但是感觉很乱,有好几个函数被调用了好几次,有的函数内部有if判断还有嵌套函数,极大影响我们的思路,这里可以使用frida trace工具来帮我们分析调用流程

20 frida trace是github上的一个工具,可以自行去下载解压后放到ida的plugis目录下,重启ida 

21 这里还有几个好用的ida插件signsrch,findhash,可以识别一些加密特征来判断是什么加密. 这里直接点一下traceNatives会生成一条命令,终端执行一下 

22 接下来主动调用一下java层的函数,它会给我们打印函数调用流程,这样就清晰多了,这里的函数地址默认都加了1,因为这个so是thumb指令的

23 我们上面分析到1B88,后面的函数你可以一一hook,到这里我感觉写的内容有点多了,我怕你们没耐心看完,所以就不带你们一个一个函数hook了

24 这个sub1105就是魔改的md5算法 

25 最终会加密3次md5,每一次md5都是魔改的,共同的魔改是这里传进去的都是md5 update的字节,而且这个字节你实现的话必须要魔改原本的md5算法.除此以外,第一次还魔改了循环左移,第二次还魔改了初始化魔数和循环左移,并且初始化魔数并不是固定的,而是由第一次加密的md5结果处理生成的,第三次加密的字节需要由第二次加密的结果提供,也就是说,最终的加密结果需要依靠前两次加密的

26 说完了这些我们直接开始hook,下面的代码是简化后的,略去了无效的输出,方便阅读

var soAddr = Module.findBaseAddress("libCrypt.so");
var funcAddr = soAddr.add(0x1104+1)  //32位+1

var num = 0
Interceptor.attach(funcAddr,{
            onEnter: function(args){
                num+=1
                console.log(`===============${num}============================`)
                console.log('onEnter arg[0]: ',hexdump(args[0]))
                console.log('onEnter arg[1]: ',hexdump(args[1]))
                console.log('onEnter arg[2]: ',hexdump(args[2]))
                this.arg1 = args[1]
            },
            onLeave: function(retval){
                    console.log('onLeave arg[1]: ',hexdump(this.arg1))
            }
        });

27 这里我结合ida中的代码分析a1和a2,a3是什么

28 选中a1,发现它一直在被32减去它的一个值并赋值给另一个值,而复制的值参与了64轮加密

29 这里我们把减号改成加号再转hex,接着对比着c++中的md5可以发现k值并没有被魔改,7,12,17,22是循环左移的次数,并且他是交替着的,我们发现下图中的v82 v83 v6 v76也是交替着的,这也就意味着a1就是循环左移的次数,循环左移你们可以上网搜索了解一下, 4个字节32位,它一直要被32减去的原因可能是他在循环右移,因为32字节的数左移一个数相当于右移32减去这个数

30我们来看看传进去的3个a1参数长啥样

31 第一组

32 第二组 

33 第三组,07 0c 11 16十进制也就是07 12 17 22,这不就是循环左移的次数吗,对比了下剩下的,发现第三个加密循环左移是标准的

34 如果你分不清是so层是循环左移还是右移那你可以拿这16个字节和被32减去的数值分别进行加密,如果其他地方没有被魔改,那么一定有一个是对的

好了,接下来看a2参数,看到01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 这组数据你就应该想到md5加密的4组初始化魔数

35 对比着C++中的md5,注意这里同样是以4个字节进行小端序排列

36 从so中的取值中也能判断出来 

37 参数3是md5明文updata后的字节,注意这是被填充过的,从终端可以看出

38 接下来分析3个魔改加密的实现,我喜欢从后往前推

39 把看似明文的东西md5以下,发现结果是正确的,但你千万不要觉得传进去的是明文,我上面圈了80 00 ...和c0 00 00 00 00 00 00 00,还记得前面介绍的填充和附加消息长度吗,就是这两个,所以传进去的是updata的字节!我前后强调很多遍了!!!

 40 那么接下来就应该分析j79Yb6ILYA602iiagzMVUw==是哪来的 你不用想也知道这肯定是第二次的加密结果某种形式变化的

 

41 也就是说8f bf 58 6f a2 0b 60 0e b4 da 28 9a 83 33 15 53怎么变成j79Yb6ILYA602iiagzMVUw==的

42 大胆猜测一下,第二次加密和第三次加密前不是进行了一堆函数操作吗,当然只有部分函数做了处理,还有一些加密的准备工作

43 这里我就大胆猜测 

44 j79Yb6ILYA602iiagzMVUw==看着像base64,把它from base64一下看看

45 啥,乱码?别急,转16进制看看,上面的 8f bf 58 6f a2 0b 60 0e b4 da 28 9a 83 33 15 53不就是16进制的吗,你猜怎么着?

46 结果很显然了, 8f bf 58 6f a2 0b 60 0e b4 da 28 9a 83 33 15 53from hex 后to base64就是j79Yb6ILYA602iiagzMVUw==

47 所以接下来就清晰了,分析第二次加密

48 明文是0ZztEbNCIcDKL3hoF/A==,这是我们主动调用的加密字符串的一部分,那另一部分呢,等等,另一部分是64字节,512bit,这不就是md5的分组长度吗

49  我们再来看看第一次加密的参数,正是我们所说的前512bit

50 也就是说so把23eedd78b2b95ef16b82da4fe2177bdcb1920dd6user/login16751641924oKc0ZztEbNCIcDKL3hoF/A==,这整个字符串进行updata和填充到1024bit,因为md5处理的字节必须是512的整数倍,并分了两组,第一组由第一次加密得到,得到的结果做为第二次加密的初始化魔数传入,并加密第二组的512bit得到第三次加密的16进制参数

51好像是这样,那怎么验证呢,因为这两次md5传入的字节都不是完整的,相当于让我把一个字符串update得到的两组512bit拆开加密,这该如何是好啊?

52 所以这就需要你对md5的加密流程足够了解,你才能去改md5的源代码来达到上面所说的效果,那我们先来看第一组加密的吧

53 这两次加密的循环左移都需要改,这里我提前改了

/* Round 1 */
FF(a, b, c, d, x[0], 0, 0xd76aa478); /* 1 */
FF(d, a, b, c, x[1], 1, 0xe8c7b756); /* 2 */
FF(c, d, a, b, x[2], 2, 0x242070db); /* 3 */
FF(b, c, d, a, x[3], 3, 0xc1bdceee); /* 4 */
FF(a, b, c, d, x[4], 0, 0xf57c0faf); /* 5 */
FF(d, a, b, c, x[5], 1, 0x4787c62a); /* 6 */
FF(c, d, a, b, x[6], 2, 0xa8304613); /* 7 */
FF(b, c, d, a, x[7], 3, 0xfd469501); /* 8 */
FF(a, b, c, d, x[8], 0, 0x698098d8); /* 9 */
FF(d, a, b, c, x[9], 1, 0x8b44f7af); /* 10 */
FF(c, d, a, b, x[10], 2, 0xffff5bb1); /* 11 */
FF(b, c, d, a, x[11], 3, 0x895cd7be); /* 12 */
FF(a, b, c, d, x[12], 0, 0x6b901122); /* 13 */
FF(d, a, b, c, x[13], 1, 0xfd987193); /* 14 */
FF(c, d, a, b, x[14], 2, 0xa679438e); /* 15 */
FF(b, c, d, a, x[15], 3, 0x49b40821); /* 16 */

/* Round 2 */
GG(a, b, c, d, x[1], 4, 0xf61e2562); /* 17 */
GG(d, a, b, c, x[6], 5, 0xc040b340); /* 18 */
GG(c, d, a, b, x[11], 6, 0x265e5a51); /* 19 */
GG(b, c, d, a, x[0], 7, 0xe9b6c7aa); /* 20 */
GG(a, b, c, d, x[5], 4, 0xd62f105d); /* 21 */
GG(d, a, b, c, x[10], 5, 0x2441453); /* 22 */
GG(c, d, a, b, x[15], 6, 0xd8a1e681); /* 23 */
GG(b, c, d, a, x[4], 7, 0xe7d3fbc8); /* 24 */
GG(a, b, c, d, x[9], 4, 0x21e1cde6); /* 25 */
GG(d, a, b, c, x[14], 5, 0xc33707d6); /* 26 */
GG(c, d, a, b, x[3], 6, 0xf4d50d87); /* 27 */
GG(b, c, d, a, x[8], 7, 0x455a14ed); /* 28 */
GG(a, b, c, d, x[13], 4, 0xa9e3e905); /* 29 */
GG(d, a, b, c, x[2], 5, 0xfcefa3f8); /* 30 */
GG(c, d, a, b, x[7], 6, 0x676f02d9); /* 31 */
GG(b, c, d, a, x[12], 7, 0x8d2a4c8a); /* 32 */

/* Round 3 */
HH(a, b, c, d, x[5], 8, 0xfffa3942); /* 33 */
HH(d, a, b, c, x[8], 9, 0x8771f681); /* 34 */
HH(c, d, a, b, x[11], 10, 0x6d9d6122); /* 35 */
HH(b, c, d, a, x[14], 11, 0xfde5380c); /* 36 */
HH(a, b, c, d, x[1], 8, 0xa4beea44); /* 37 */
HH(d, a, b, c, x[4], 9, 0x4bdecfa9); /* 38 */
HH(c, d, a, b, x[7], 10, 0xf6bb4b60); /* 39 */
HH(b, c, d, a, x[10], 11, 0xbebfbc70); /* 40 */
HH(a, b, c, d, x[13], 8, 0x289b7ec6); /* 41 */
HH(d, a, b, c, x[0], 9, 0xeaa127fa); /* 42 */
HH(c, d, a, b, x[3], 10, 0xd4ef3085); /* 43 */
HH(b, c, d, a, x[6], 11, 0x4881d05); /* 44 */
HH(a, b, c, d, x[9], 8, 0xd9d4d039); /* 45 */
HH(d, a, b, c, x[12], 9, 0xe6db99e5); /* 46 */
HH(c, d, a, b, x[15], 10, 0x1fa27cf8); /* 47 */
HH(b, c, d, a, x[2], 11, 0xc4ac5665); /* 48 */

/* Round 4 */
II(a, b, c, d, x[0], 12, 0xf4292244); /* 49 */
II(d, a, b, c, x[7], 13, 0x432aff97); /* 50 */
II(c, d, a, b, x[14], 14, 0xab9423a7); /* 51 */
II(b, c, d, a, x[5], 15, 0xfc93a039); /* 52 */
II(a, b, c, d, x[12], 12, 0x655b59c3); /* 53 */
II(d, a, b, c, x[3], 13, 0x8f0ccc92); /* 54 */
II(c, d, a, b, x[10], 14, 0xffeff47d); /* 55 */
II(b, c, d, a, x[1], 15, 0x85845dd1); /* 56 */
II(a, b, c, d, x[8], 12, 0x6fa87e4f); /* 57 */
II(d, a, b, c, x[15], 13, 0xfe2ce6e0); /* 58 */
II(c, d, a, b, x[6], 14, 0xa3014314); /* 59 */
II(b, c, d, a, x[13], 15, 0x4e0811a1); /* 60 */
II(a, b, c, d, x[4], 12, 0xf7537e82); /* 61 */
II(d, a, b, c, x[11], 13, 0xbd3af235); /* 62 */
II(c, d, a, b, x[2], 14, 0x2ad7d2bb); /* 63 */
II(b, c, d, a, x[9], 15, 0xeb86d391); /* 64 */

54 接下来我们需要做的事是把明文传的23eedd78b2b95ef16b82da4fe2177bdcb1920dd6user/login16751641924oKc,最终MD5Encode的时候压入的字节和下图一样即可

55 怎么操作呢,我直接说结论了,由于传参刚好是512bit,所以只需要把填充和附加消息长度的地方注释即可

56 最终结果也是成功得到了

57 接一下就是改第二次加密的初始化魔数,可以仿照着01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10 按小端字节序排列

58 接下来改updata的字节 

59 这里主要改小端字节序,为什么呢,因为填充的80是直接跟着明文的字节,而小端字节序是有明文的长度决定的,注意这里的长度是整个长度,之前说过了, 

60          00 00 00 00 00 00 02 a8    a8代表的是168bit,21字节,正是0ZztEbNCIcDKL3hoF/A==的字符个数,02代表的是512bit,64字节,也就是前面的那串

61 c++md5中由于只有168字符,所以我们需要手动改消息长度的内容,怎么改呢,很简单 a8 00 00 00 00 00 00 00 改a8 02 00 00 00 00 00 00怎么改?

62 很简单中间改bits的值就好了,加上一句bits[1]=2;

 63 结果也就验证成功了,那么怎么写活呢,结尾我会附上完整python代码

总结:

本次教学干货很多,由于考虑单篇文章的阅读时间,我省略了部分无关紧要的流程,核心流程都在里面了.

说实话写这个sign算法的人水平很高,他对md5算法肯定是有充分了解和把握的,一般改改初始化魔数,改改k值都很少见,他一个算法里连着改那么多算是比较少见了.

提一点,关于那个魔改的md5函数,你可以结合着so层主动调用,不过你需要传3个指针参数,但是不太好构造,我这里采取的是直接修改so层传的第3个参数的值来验证的(本文并未提及),如果没有我上面说的前提,你自己摸索需要不断进行验证推翻再验证的过程,逆向就是这个样子的.

本人写作水平有限,如有讲解不到位或者讲解错误的地方,还请各位大佬在评论区多多指教,共同进步,也可加本人微信lyaoyao__i(两个_)

python代码:

import struct
import base64
from loguru import logger
class sign():
    def __init__(self):
        pass
    def md5_1(self,message):
        def left_rotate(x, amount):
            return ((x << amount) | (x >> (32 - amount))) & 0xFFFFFFFF
        def F(x, y, z):
            return (x & y) | (~x & z)
        def G(x, y, z):
            return (x & z) | (y & ~z)
        def H(x, y, z):
            return x ^ y ^ z
        def I(x, y, z):
            return y ^ (x | ~z)
        def FF(a, b, c, d, x, s, ac):
            a = (a + F(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF
        def GG(a, b, c, d, x, s, ac):
            a = (a + G(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF
        def HH(a, b, c, d, x, s, ac):
            a = (a + H(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF
        def II(a, b, c, d, x, s, ac):
            a = (a + I(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF
        def pad_message(message):
            # original_length_bits = len(message) * 8
            # message += b'\x80'
            # while (len(message) + 8) % 64 != 0:
            #     message += b'\x00'
            # message += struct.pack('<Q', original_length_bits)    # 填充
            return message
        a0 = 0x67452301
        b0 = 0xEFCDAB89
        c0 = 0x98BADCFE
        d0 = 0x10325476
        message = pad_message(message)
        chunks = [message[i:i+64] for i in range(0, len(message), 64)]
        for chunk in chunks:
            words = struct.unpack('<16I', chunk)
            A, B, C, D = a0, b0, c0, d0
            # Round 1
            A = FF(A, B, C, D, words[0], 0, 0xD76AA478)
            D = FF(D, A, B, C, words[1], 1, 0xE8C7B756)
            C = FF(C, D, A, B, words[2], 2, 0x242070DB)
            B = FF(B, C, D, A, words[3], 3, 0xC1BDCEEE)
            A = FF(A, B, C, D, words[4], 0, 0xF57C0FAF)
            D = FF(D, A, B, C, words[5], 1, 0x4787C62A)
            C = FF(C, D, A, B, words[6], 2, 0xA8304613)
            B = FF(B, C, D, A, words[7], 3, 0xFD469501)
            A = FF(A, B, C, D, words[8], 0, 0x698098D8)
            D = FF(D, A, B, C, words[9], 1, 0x8B44F7AF)
            C = FF(C, D, A, B, words[10], 2, 0xFFFF5BB1)
            B = FF(B, C, D, A, words[11], 3, 0x895CD7BE)
            A = FF(A, B, C, D, words[12], 0, 0x6B901122)
            D = FF(D, A, B, C, words[13], 1, 0xFD987193)
            C = FF(C, D, A, B, words[14], 2, 0xA679438E)
            B = FF(B, C, D, A, words[15], 3, 0x49B40821)
            # Round 2
            A = GG(A, B, C, D, words[1], 4, 0xF61E2562)
            D = GG(D, A, B, C, words[6], 5, 0xC040B340)
            C = GG(C, D, A, B, words[11], 6, 0x265E5A51)
            B = GG(B, C, D, A, words[0], 7, 0xE9B6C7AA)
            A = GG(A, B, C, D, words[5], 4, 0xD62F105D)
            D = GG(D, A, B, C, words[10], 5, 0x02441453)
            C = GG(C, D, A, B, words[15], 6, 0xD8A1E681)
            B = GG(B, C, D, A, words[4], 7, 0xE7D3FBC8)
            A = GG(A, B, C, D, words[9], 4, 0x21E1CDE6)
            D = GG(D, A, B, C, words[14], 5, 0xC33707D6)
            C = GG(C, D, A, B, words[3], 6, 0xF4D50D87)
            B = GG(B, C, D, A, words[8], 7, 0x455A14ED)
            A = GG(A, B, C, D, words[13], 4, 0xA9E3E905)
            D = GG(D, A, B, C, words[2], 5, 0xFCEFA3F8)
            C = GG(C, D, A, B, words[7], 6, 0x676F02D9)
            B = GG(B, C, D, A, words[12], 7, 0x8D2A4C8A)
            # Round 3
            A = HH(A, B, C, D, words[5], 8, 0xFFFA3942)
            D = HH(D, A, B, C, words[8], 9, 0x8771F681)
            C = HH(C, D, A, B, words[11], 10, 0x6D9D6122)
            B = HH(B, C, D, A, words[14], 11, 0xFDE5380C)
            A = HH(A, B, C, D, words[1], 8, 0xA4BEEA44)
            D = HH(D, A, B, C, words[4], 9, 0x4BDECFA9)
            C = HH(C, D, A, B, words[7], 10, 0xF6BB4B60)
            B = HH(B, C, D, A, words[10], 11, 0xBEBFBC70)
            A = HH(A, B, C, D, words[13], 8, 0x289B7EC6)
            D = HH(D, A, B, C, words[0], 9, 0xEAA127FA)
            C = HH(C, D, A, B, words[3], 10, 0xD4EF3085)
            B = HH(B, C, D, A, words[6], 11, 0x04881D05)
            A = HH(A, B, C, D, words[9], 8, 0xD9D4D039)
            D = HH(D, A, B, C, words[12], 9, 0xE6DB99E5)
            C = HH(C, D, A, B, words[15], 10, 0x1FA27CF8)
            B = HH(B, C, D, A, words[2], 11, 0xC4AC5665)
            # Round 4
            A = II(A, B, C, D, words[0], 12, 0xF4292244)
            D = II(D, A, B, C, words[7], 13, 0x432AFF97)
            C = II(C, D, A, B, words[14], 14, 0xAB9423A7)
            B = II(B, C, D, A, words[5], 15, 0xFC93A039)
            A = II(A, B, C, D, words[12], 12, 0x655B59C3)
            D = II(D, A, B, C, words[3], 13, 0x8F0CCC92)
            C = II(C, D, A, B, words[10], 14, 0xFFEFF47D)
            B = II(B, C, D, A, words[1], 15, 0x85845DD1)
            A = II(A, B, C, D, words[8], 12, 0x6FA87E4F)
            D = II(D, A, B, C, words[15], 13, 0xFE2CE6E0)
            C = II(C, D, A, B, words[6], 14, 0xA3014314)
            B = II(B, C, D, A, words[13], 15, 0x4E0811A1)
            A = II(A, B, C, D, words[4], 12, 0xF7537E82)
            D = II(D, A, B, C, words[11], 13, 0xBD3AF235)
            C = II(C, D, A, B, words[2], 14, 0x2AD7D2BB)
            B = II(B, C, D, A, words[9], 15, 0xEB86D391)

            a0 = (a0 + A) & 0xFFFFFFFF
            b0 = (b0 + B) & 0xFFFFFFFF
            c0 = (c0 + C) & 0xFFFFFFFF
            d0 = (d0 + D) & 0xFFFFFFFF

        result = struct.pack('<4I', a0, b0, c0, d0)
        return result.hex()
    def md5_2(self,message,_result,length):
        def left_rotate(x, amount):
            return ((x << amount) | (x >> (32 - amount))) & 0xFFFFFFFF
        def F(x, y, z):
            return (x & y) | (~x & z)
        def G(x, y, z):
            return (x & z) | (y & ~z)
        def H(x, y, z):
            return x ^ y ^ z
        def I(x, y, z):
            return y ^ (x | ~z)
        def FF(a, b, c, d, x, s, ac):
            a = (a + F(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF
        def GG(a, b, c, d, x, s, ac):
            a = (a + G(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF
        def HH(a, b, c, d, x, s, ac):
            a = (a + H(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF
        def II(a, b, c, d, x, s, ac):
            a = (a + I(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF
        def pad_message(message):
            original_length_bits = len(message) * 8
            message += b'\x80'
            while (len(message) + 8) % 64 != 0:
                message += b'\x00'
            message += struct.pack('<Q', original_length_bits)
            return message
        a0 = int(hex(_result[0]), 16)
        b0 = int(hex(_result[1]), 16)
        c0 = int(hex(_result[2]), 16)
        d0 = int(hex(_result[3]), 16)
        message = pad_message(message)   #448 255
        if(length<256):
            # 1组就一个
            _hex= hex(length)
            index_to_replace = message.rindex(bytes.fromhex(_hex[2:]))
            # 将目标位置替换为 0x02
            message = message[:index_to_replace + 1] + b'\x02' + message[index_to_replace + 2:]

        else:
            _hex = hex(length-256)
            index_to_replace = message.rindex(bytes.fromhex(_hex[2:]))
            # 将目标位置替换为 0x03
            message = message[:index_to_replace + 1] + b'\x03' + message[index_to_replace + 2:]


        chunks = [message[i:i+64] for i in range(0, len(message), 64)]
        for chunk in chunks:
            words = struct.unpack('<16I', chunk)
            A, B, C, D = a0, b0, c0, d0
            # Round 1
            A = FF(A, B, C, D, words[0], 0, 0xD76AA478)
            D = FF(D, A, B, C, words[1], 1, 0xE8C7B756)
            C = FF(C, D, A, B, words[2], 2, 0x242070DB)
            B = FF(B, C, D, A, words[3], 3, 0xC1BDCEEE)
            A = FF(A, B, C, D, words[4], 0, 0xF57C0FAF)
            D = FF(D, A, B, C, words[5], 1, 0x4787C62A)
            C = FF(C, D, A, B, words[6], 2, 0xA8304613)
            B = FF(B, C, D, A, words[7], 3, 0xFD469501)
            A = FF(A, B, C, D, words[8], 0, 0x698098D8)
            D = FF(D, A, B, C, words[9], 1, 0x8B44F7AF)
            C = FF(C, D, A, B, words[10], 2, 0xFFFF5BB1)
            B = FF(B, C, D, A, words[11], 3, 0x895CD7BE)
            A = FF(A, B, C, D, words[12], 0, 0x6B901122)
            D = FF(D, A, B, C, words[13], 1, 0xFD987193)
            C = FF(C, D, A, B, words[14], 2, 0xA679438E)
            B = FF(B, C, D, A, words[15], 3, 0x49B40821)
            # Round 2
            A = GG(A, B, C, D, words[1], 4, 0xF61E2562)
            D = GG(D, A, B, C, words[6], 5, 0xC040B340)
            C = GG(C, D, A, B, words[11], 6, 0x265E5A51)
            B = GG(B, C, D, A, words[0], 7, 0xE9B6C7AA)
            A = GG(A, B, C, D, words[5], 4, 0xD62F105D)
            D = GG(D, A, B, C, words[10], 5, 0x02441453)
            C = GG(C, D, A, B, words[15], 6, 0xD8A1E681)
            B = GG(B, C, D, A, words[4], 7, 0xE7D3FBC8)
            A = GG(A, B, C, D, words[9], 4, 0x21E1CDE6)
            D = GG(D, A, B, C, words[14], 5, 0xC33707D6)
            C = GG(C, D, A, B, words[3], 6, 0xF4D50D87)
            B = GG(B, C, D, A, words[8], 7, 0x455A14ED)
            A = GG(A, B, C, D, words[13], 4, 0xA9E3E905)
            D = GG(D, A, B, C, words[2], 5, 0xFCEFA3F8)
            C = GG(C, D, A, B, words[7], 6, 0x676F02D9)
            B = GG(B, C, D, A, words[12], 7, 0x8D2A4C8A)
            # Round 3
            A = HH(A, B, C, D, words[5], 8, 0xFFFA3942)
            D = HH(D, A, B, C, words[8], 9, 0x8771F681)
            C = HH(C, D, A, B, words[11], 10, 0x6D9D6122)
            B = HH(B, C, D, A, words[14], 11, 0xFDE5380C)
            A = HH(A, B, C, D, words[1], 8, 0xA4BEEA44)
            D = HH(D, A, B, C, words[4], 9, 0x4BDECFA9)
            C = HH(C, D, A, B, words[7], 10, 0xF6BB4B60)
            B = HH(B, C, D, A, words[10], 11, 0xBEBFBC70)
            A = HH(A, B, C, D, words[13], 8, 0x289B7EC6)
            D = HH(D, A, B, C, words[0], 9, 0xEAA127FA)
            C = HH(C, D, A, B, words[3], 10, 0xD4EF3085)
            B = HH(B, C, D, A, words[6], 11, 0x04881D05)
            A = HH(A, B, C, D, words[9], 8, 0xD9D4D039)
            D = HH(D, A, B, C, words[12], 9, 0xE6DB99E5)
            C = HH(C, D, A, B, words[15], 10, 0x1FA27CF8)
            B = HH(B, C, D, A, words[2], 11, 0xC4AC5665)
            # Round 4
            A = II(A, B, C, D, words[0], 12, 0xF4292244)
            D = II(D, A, B, C, words[7], 13, 0x432AFF97)
            C = II(C, D, A, B, words[14], 14, 0xAB9423A7)
            B = II(B, C, D, A, words[5], 15, 0xFC93A039)
            A = II(A, B, C, D, words[12], 12, 0x655B59C3)
            D = II(D, A, B, C, words[3], 13, 0x8F0CCC92)
            C = II(C, D, A, B, words[10], 14, 0xFFEFF47D)
            B = II(B, C, D, A, words[1], 15, 0x85845DD1)
            A = II(A, B, C, D, words[8], 12, 0x6FA87E4F)
            D = II(D, A, B, C, words[15], 13, 0xFE2CE6E0)
            C = II(C, D, A, B, words[6], 14, 0xA3014314)
            B = II(B, C, D, A, words[13], 15, 0x4E0811A1)
            A = II(A, B, C, D, words[4], 12, 0xF7537E82)
            D = II(D, A, B, C, words[11], 13, 0xBD3AF235)
            C = II(C, D, A, B, words[2], 14, 0x2AD7D2BB)
            B = II(B, C, D, A, words[9], 15, 0xEB86D391)
            a0 = (a0 + A) & 0xFFFFFFFF
            b0 = (b0 + B) & 0xFFFFFFFF
            c0 = (c0 + C) & 0xFFFFFFFF
            d0 = (d0 + D) & 0xFFFFFFFF
        result = struct.pack('<4I', a0, b0, c0, d0)
        return result.hex()
    def md5_3(self,message):
        def left_rotate(x, amount):
            return ((x << amount) | (x >> (32 - amount))) & 0xFFFFFFFF

        def F(x, y, z):
            return (x & y) | (~x & z)

        def G(x, y, z):
            return (x & z) | (y & ~z)

        def H(x, y, z):
            return x ^ y ^ z

        def I(x, y, z):
            return y ^ (x | ~z)

        def FF(a, b, c, d, x, s, ac):
            a = (a + F(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF

        def GG(a, b, c, d, x, s, ac):
            a = (a + G(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF

        def HH(a, b, c, d, x, s, ac):
            a = (a + H(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF

        def II(a, b, c, d, x, s, ac):
            a = (a + I(b, c, d) + x + ac) & 0xFFFFFFFF
            return left_rotate(a, s) + b & 0xFFFFFFFF

        def pad_message(message):
            original_length_bits = len(message) * 8
            message += b'\x80'
            while (len(message) + 8) % 64 != 0:
                message += b'\x00'
            message += struct.pack('<Q', original_length_bits)
            return message

        a0 = 0x67452301
        b0 = 0xEFCDAB89
        c0 = 0x98BADCFE
        d0 = 0x10325476

        message = pad_message(message)
        chunks = [message[i:i+64] for i in range(0, len(message), 64)]

        for chunk in chunks:
            words = struct.unpack('<16I', chunk)
            A, B, C, D = a0, b0, c0, d0

            # Round 1
            A = FF(A, B, C, D, words[0], 7, 0xD76AA478)
            D = FF(D, A, B, C, words[1], 12, 0xE8C7B756)
            C = FF(C, D, A, B, words[2], 17, 0x242070DB)
            B = FF(B, C, D, A, words[3], 22, 0xC1BDCEEE)
            A = FF(A, B, C, D, words[4], 7, 0xF57C0FAF)
            D = FF(D, A, B, C, words[5], 12, 0x4787C62A)
            C = FF(C, D, A, B, words[6], 17, 0xA8304613)
            B = FF(B, C, D, A, words[7], 22, 0xFD469501)
            A = FF(A, B, C, D, words[8], 7, 0x698098D8)
            D = FF(D, A, B, C, words[9], 12, 0x8B44F7AF)
            C = FF(C, D, A, B, words[10], 17, 0xFFFF5BB1)
            B = FF(B, C, D, A, words[11], 22, 0x895CD7BE)
            A = FF(A, B, C, D, words[12], 7, 0x6B901122)
            D = FF(D, A, B, C, words[13], 12, 0xFD987193)
            C = FF(C, D, A, B, words[14], 17, 0xA679438E)
            B = FF(B, C, D, A, words[15], 22, 0x49B40821)

            # Round 2
            A = GG(A, B, C, D, words[1], 5, 0xF61E2562)
            D = GG(D, A, B, C, words[6], 9, 0xC040B340)
            C = GG(C, D, A, B, words[11], 14, 0x265E5A51)
            B = GG(B, C, D, A, words[0], 20, 0xE9B6C7AA)
            A = GG(A, B, C, D, words[5], 5, 0xD62F105D)
            D = GG(D, A, B, C, words[10], 9, 0x02441453)
            C = GG(C, D, A, B, words[15], 14, 0xD8A1E681)
            B = GG(B, C, D, A, words[4], 20, 0xE7D3FBC8)
            A = GG(A, B, C, D, words[9], 5, 0x21E1CDE6)
            D = GG(D, A, B, C, words[14], 9, 0xC33707D6)
            C = GG(C, D, A, B, words[3], 14, 0xF4D50D87)
            B = GG(B, C, D, A, words[8], 20, 0x455A14ED)
            A = GG(A, B, C, D, words[13], 5, 0xA9E3E905)
            D = GG(D, A, B, C, words[2], 9, 0xFCEFA3F8)
            C = GG(C, D, A, B, words[7], 14, 0x676F02D9)
            B = GG(B, C, D, A, words[12], 20, 0x8D2A4C8A)

            # Round 3
            A = HH(A, B, C, D, words[5], 4, 0xFFFA3942)
            D = HH(D, A, B, C, words[8], 11, 0x8771F681)
            C = HH(C, D, A, B, words[11], 16, 0x6D9D6122)
            B = HH(B, C, D, A, words[14], 23, 0xFDE5380C)
            A = HH(A, B, C, D, words[1], 4, 0xA4BEEA44)
            D = HH(D, A, B, C, words[4], 11, 0x4BDECFA9)
            C = HH(C, D, A, B, words[7], 16, 0xF6BB4B60)
            B = HH(B, C, D, A, words[10], 23, 0xBEBFBC70)
            A = HH(A, B, C, D, words[13], 4, 0x289B7EC6)
            D = HH(D, A, B, C, words[0], 11, 0xEAA127FA)
            C = HH(C, D, A, B, words[3], 16, 0xD4EF3085)
            B = HH(B, C, D, A, words[6], 23, 0x04881D05)
            A = HH(A, B, C, D, words[9], 4, 0xD9D4D039)
            D = HH(D, A, B, C, words[12], 11, 0xE6DB99E5)
            C = HH(C, D, A, B, words[15], 16, 0x1FA27CF8)
            B = HH(B, C, D, A, words[2], 23, 0xC4AC5665)

            # Round 4
            A = II(A, B, C, D, words[0], 6, 0xF4292244)
            D = II(D, A, B, C, words[7], 10, 0x432AFF97)
            C = II(C, D, A, B, words[14], 15, 0xAB9423A7)
            B = II(B, C, D, A, words[5], 21, 0xFC93A039)
            A = II(A, B, C, D, words[12], 6, 0x655B59C3)
            D = II(D, A, B, C, words[3], 10, 0x8F0CCC92)
            C = II(C, D, A, B, words[10], 15, 0xFFEFF47D)
            B = II(B, C, D, A, words[1], 21, 0x85845DD1)
            A = II(A, B, C, D, words[8], 6, 0x6FA87E4F)
            D = II(D, A, B, C, words[15], 10, 0xFE2CE6E0)
            C = II(C, D, A, B, words[6], 15, 0xA3014314)
            B = II(B, C, D, A, words[13], 21, 0x4E0811A1)
            A = II(A, B, C, D, words[4], 6, 0xF7537E82)
            D = II(D, A, B, C, words[11], 10, 0xBD3AF235)
            C = II(C, D, A, B, words[2], 15, 0x2AD7D2BB)
            B = II(B, C, D, A, words[9], 21, 0xEB86D391)

            a0 = (a0 + A) & 0xFFFFFFFF
            b0 = (b0 + B) & 0xFFFFFFFF
            c0 = (c0 + C) & 0xFFFFFFFF
            d0 = (d0 + D) & 0xFFFFFFFF

        result = struct.pack('<4I', a0, b0, c0, d0)
        return result.hex()
    def main(self,_str):
        str1 = _str[:64]
        str2 = _str[64:]
        # 示例用法
        res1 = self.md5_1(str1.encode('utf-8'))
        logger.info(f'第一次md5初始化魔数分割前的加密结果==>{res1}')

        # 将原始哈希字符串转换为字节对象
        original_bytes = bytes.fromhex(res1)
        # 使用 struct 模块按照规律解析字节对象并生成新的四组
        _result = [struct.unpack('<I', original_bytes[i:i + 4])[0] for i in range(0, len(original_bytes), 4)]
        logger.info(f'初始化魔数==>a1={hex(_result[0])}  a2={hex(_result[1])}  a3={hex(_result[2])}  a4={hex(_result[3])}')

        res2 = self.md5_2(str2.encode('utf-8'),_result,len(str2)*8)
        res_2 = base64.b64encode(bytes.fromhex(res2)).decode('utf-8')
        logger.info(f'第二次md5结果==>{res2},是最终加密结果的明文')

        sign = self.md5_3(res_2.encode('utf-8'))
        logger.info(f'第三次md5最终sign结果==>{sign}')


obj = sign()
obj.main('23eedd78b2b95ef16b82da4fe2177bdcb1920dd6user/login16751641924oKc0ZztEbNCIcDKL3hoF/A==')

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

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

相关文章

Java项目实战《苍穹外卖》 二、项目搭建

当我痛苦地站在你的面前 你不能说我一无所有 你不能说我两手空空 系列文章目录 苍穹外卖是黑马程序员2023年的Java实战项目&#xff0c;作为业余练手用&#xff0c;需要源码或者课程的可以找我&#xff0c;无偿分享 Java项目实战《苍穹外卖》 一、项目概述Java项目实战《苍穹外…

c# webapi 处理跨源问题

利用cors中间件处理跨源问题。 首先&#xff0c;什么是跨域&#xff08;跨源&#xff09;问题&#xff1a; 是指不同站点之间&#xff0c;使用ajax无法相互调用的问题。跨域问题本质是浏览器的一种保护机制&#xff0c;它的初衷是为了保证用户的安全&#xff0c;防止恶意网站窃…

【C语言数据结构】单链表

目录 分析顺序表和链表实现单链表打印链表动态申请一个节点尾插头插尾删头删查找值函数单链表在pos位置之前插入x单链表在pos位置之后插入x删除pos位置单链表删除pos位置之后的值释放内存空间 分析顺序表和链表 如下图可以看出顺序表的优点 1.尾插尾删足够快 2.下标随机访问和修…

鸿蒙开发|开启鸿蒙开发之旅-发工具下载安装、项目创建和预览

文章目录 一、鸿蒙开发使用语言二、下载开发工具三、安装开发工具四、新建项目五、项目启动 一、鸿蒙开发使用语言 鸿蒙OS开发支持多种编程语言&#xff0c;开发者可以根据自身技术背景和项目需求选择合适的语言进行开发。目前鸿蒙OS主要支持以下几种语言&#xff1a; Java&am…

计算机msvcp120.dll丢失?msvcp120.dll丢失5种简单的解决方法分享

你们是否在电脑操作过程中常看到一段类似“msvcp120.dll缺失或损坏”的报错信息&#xff1f;这可能会干扰大家的日常应用程序使用&#xff0c;怎么办呢&#xff1f;别担心&#xff0c;接下来就是一篇详细的步骤来教你如何应对这种情况&#xff0c;让你们的电脑运作如初&#xf…

二叉树的遍历(非递归版)

文章目录 二叉树的前序遍历二叉树的中序遍历二叉树的后序遍历 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站。 二叉树的前序遍历 用递归实…

文件加密软件哪个好用丨真心推荐丨良心建议

在保护企业文件和数据方面&#xff0c;文件加密软件是一种非常重要的工具。以下是我推荐好用的文件加密软件&#xff0c;以及我的良心建议。 一、WinRAR。WinRAR是一款免费的文件压缩和解压缩工具&#xff0c;同时也提供了强大的文件加密功能。使用WinRAR可以轻松地加密文件夹和…

算法通关村第十关-白银挑战数组最大K数

大家好我是苏麟 , 今天带来一道应用快排的题 . 数组中的第K个最大元素 描述 : 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。 请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。 题目 : Le…

【机器学习Python实战】线性回归

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习python实战 欢迎订阅&#xff01;后面的内容会越来越有意思~ ⭐内容说明&#xff1a;本专栏主要针对机器学习专栏的基础内容进行python的实现&#xff0c;部分…

从零开始:抖音酒店景区小程序开发指南

为了满足用户多样化的需求&#xff0c;开发一款抖音酒店景区小程序成为了业界的一个新兴趋势。在这篇文章中&#xff0c;我们将探讨如何开发一款引人注目的抖音风格的酒店景区小程序。 一、抖音风格的设计理念 在设计酒店景区小程序时&#xff0c;我们需要融入抖音的设计理念。…

珠海希雷伺服全套(包含算法)方案

下载链接&#xff01;&#xff01;https://mp.weixin.qq.com/s?__bizMzU2OTc4ODA4OA&mid2247555038&idx1&sn939a4ad71582abc1f9e93c4d5526fed9&chksmfcfb0409cb8c8d1f74ce7108e20b0310e7399775367a023638624357644dfa4ae435e41c8768&token207079769&l…

Flink(七)【输出算子(Sink)】

前言 今天是我写博客的第 200 篇&#xff0c;恍惚间两年过去了&#xff0c;现在已经是大三的学长了。仍然记得两年前第一次写博客的时候&#xff0c;当时学的应该是 Java 语言&#xff0c;菜的一批&#xff0c;写了就删&#xff0c;怕被人看到丢脸。当时就想着自己一年之后&…

客户端性能优化实践

背景 双十一大促时&#xff0c;客户客服那边反馈商品信息加载卡顿&#xff0c;在不断有订单咨询时&#xff0c;甚至出现了商品信息一直处于加载状态的情况&#xff0c;显然&#xff0c;在这种高峰期接待客户时&#xff0c;是没法进行正常的接待工作的。 起初&#xff0c;页面一…

4、FFmpeg命令行操作8

生成测试文件 找三个不同的视频每个视频截取10秒内容 ffmpeg -i 沙海02.mp4 -ss 00:05:00 -t 10 -codec copy 1.mp4 ffmpeg -i 复仇者联盟3.mp4 -ss 00:05:00 -t 10 -codec copy 2.mp4 ffmpeg -i 红海行动.mp4 -ss 00:05:00 -t 10 -codec copy 3.mp4 如果音视…

记录一些涉及到界的题

文章目录 coppersmith的一些相关知识题1 [N1CTF 2023] e2Wrmup题2 [ACTF 2023] midRSA题3 [qsnctf 2023]浅记一下 coppersmith的一些相关知识 上界 X c e i l ( 1 2 ∗ N β 2 d − ϵ ) X ceil(\frac{1}{2} * N^{\frac{\beta^2}{d} - \epsilon}) Xceil(21​∗Ndβ2​−ϵ) …

Os-ByteSec

Os-ByteSec 一、主机发现和端口扫描 主机发现&#xff0c;靶机地址192.168.80.144 端口扫描&#xff0c;开放了80、139、445、2525端口 二、信息收集 访问80端口 路径扫描 dirsearch -u "http://192.168.80.144/" -e *访问扫描出来的路径&#xff0c;没有发现…

【有源码】基于asp.net的旅游度假村管理系统C#度假村美食住宿一体化平台源码调试 开题 lw ppt

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人七年开发经验&#xff0c;擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等&#xff0c;大家有这一块的问题可以一起交流&#xff01; &#x1f495;&…

聊聊氮化硅(SiNx)在芯片中的重要性

在芯片制造中&#xff0c;有一种材料扮演着至关重要的角色&#xff0c;那就是氮化硅&#xff08;SiNx&#xff09;。尽管它可能并未获得和其他更为熟知的半导体材料&#xff0c;如硅&#xff08;Si&#xff09;、砷化镓&#xff08;GaAs&#xff09;或氮化镓&#xff08;GaN&am…

链式队列的基本操作与实现(数据结构与算法)

链队列的表示与实现如下图&#xff1a; 代码如下&#xff1a; #include<iostream> using namespace std;#define MAXQSIZE 100 //最大队列长度 typedef int QElemType; //typedef struct Qnode {QElemType data;struct Qnode* next; }QNode, *QueuePtr; //队列结点类型…

KVM Cloud云平台

项目介绍 KVM Cloud 是一款基于Java实现的轻量级私有云平台&#xff0c;旨在帮助中小企业快速实现计算、存储、网络等资源的管理&#xff0c;让企业拥有自己的云平台&#xff0c;包括但不限于如下功能: 1、基于KVM的VM基础功能(创建、启动、停止、重装、webVNC等功能) 2、使用…