逆向工程实验——pre9(可执行文件的加密MD5碰撞lab)

1.阅读

C语言随机数的实现:mingw与glibc
https://blog.csdn.net/elicococoo/article/details/41851473

2.阅读

java 代码混淆原理
https://blog.csdn.net/u013378306/article/details/63682945
ProGuard代码混淆技术详解
http://www.cnblogs.com/cr330326/p/5534915.html

3、阅读

结构体(对齐规则及举例)
https://www.cnblogs.com/wsq-888/p/jie-gou-ti-dui-qi-gui-ze-ji-ju-li.html

4、阅读下面这三篇文章:

UAF学习–原理及利用
https://www.cnblogs.com/alert123/p/4918041.html

Linux内核提权漏洞的分析和利用(CVE-2016-0728)
http://www.freebuf.com/vuls/93799.html

通过UseAfterFree实现命令执行
https://bbs.pediy.com/thread-221537.htm
这个上个学期软件安全课已经写过了,利用UAF漏洞,实现GOT表覆盖,从而实现命令执行。

5、MD5 Collision Attack Lab

其中Task 4选做
旧链接:http://www.cis.syr.edu/~wedu/seed/Labs_16.04/Crypto/Crypto_MD5_Collision/
新链接:https://seedsecuritylabs.org/Labs_16.04/Crypto/Crypto_MD5_Collision/

Task 1:使用相同的MD5哈希值生成两个不同的文件

  在这个任务中,我们将生成两个具有相同MD5哈希值的不同文件。这两个文件的开始部分需要相同,即它们共享相同的前缀。我们可以使用md5collgen程序实现这一点,它允许我们提供具有任意内容的前缀文件。程序是如何工作的如图1所示。
在这里插入图片描述

下面的命令生成两个输出文件out1.bin和out2.bin,对于给定的前缀文件prefix.txt:

$ md5collgen -p prefix.txt -o out1.bin out2.bin

在这里插入图片描述

  我们可以使用diff命令检查输出文件是否不同。我们还可以使用md5sum命令检查每个输出文件的MD5哈希值。请参见以下命令。

$ diff out1.bin out2.bin
$ md5sum out1.bin
$ md5sum out2.bin

在这里插入图片描述

  由于outl1.bin和 ou2.bin 是二进制的,我们不能使用文本查看程序来查看它们,比如 cat或更多;我们需要使用二进制编辑器来查看(和编辑)它们。我们已经在VM中安装了一个名为 bless的十六进制编辑器软件。请使用这样的编辑器来查看这两个输出文件,并描述您的观察结果。
在这里插入图片描述
在这里插入图片描述

将两个输出文件进行文件比较:
在这里插入图片描述

  可以看到两个输出文件的二进制内容并不是完全一样的,但它们的md5值是一样的。

此外,你还应回答以下问题:

问题1:如果前缀文件的长度不是64的倍数,会发生什么?

在这里插入图片描述

diff命令显示两个输出文件是不同的,但它们的md5值相同
在这里插入图片描述

  13字节全为0的前缀文件生成的两个输出文件的前64字节都是0,后面再接上128字节的数据。说明当前缀不是64字节的倍数时会自动补0补齐64字节。

问题2:创建一个恰好64字节的前缀文件,然后再次运行碰撞工具,看看会发生什么。

在这里插入图片描述

diff命令显示两个输出文件是不同的,但它们的md5值相同
在这里插入图片描述

  恰好64字节全为0的前缀文件生成的两个输出文件的前64字节都是0,后面再接上128字节的数据。
在这里插入图片描述

  128字节全为A的前缀文件生成的两个输出文件的前128字节都是A,后面再接上128字节的数据。

问题3:md5collgen 生成的数据(128字节)对于两个输出文件是否完全不同?请识别所有不同的字节。

  两个输出文件大部分字节都相同,只有少数几个字节不同,上面这两个文件是有7个字节不同,其他的输出文件不同的字节数可能不一样。
在这里插入图片描述

  所以到这,我们也知道了md5collgen的工作原理,就是当输入文件不是64字节的倍数时先补0到64字节的倍数,再添加两个128字节的数据分别生成两个MD5值相同的输出文件。

Task 2:理解MD5的属性

  在本任务中,我们将尝试理解MD5算法的一些属性。这些特性对我们在这个实验室中进行进一步的工作非常重要。MD5是一个相当复杂的算法,但从非常高的水平来看,它并不那么复杂。如图2所示:
在这里插入图片描述

  MD5将输入数据分成64字节的块,然后在这些块上迭代计算散列。MD5 算法的核心是一个压缩函数,它接受两个输入,一个64字节的数据块和前一次迭代的结果。压缩函数产生一个128位的 IHV,代表“中间哈希值”;然后将此输出输入到下一次迭代中。如果当前迭代是最后一次迭代,则IHV将是最终的哈希值。第一次迭代的HV输入(IHV0)是一个固定值。
  根据MD5算法的工作原理,我们可以推导出MD5算法的以下属性:输入M和N,如果MD5(M) = MD5(N),即M和N的MD5哈希值相同,则对于任何输入T, MD5(M k T) = MD5(N k T),其中k表示拼接。也就是说,如果输入M和N具有相同的散列,向它们添加相同的后缀T将产生两个输出它们有相同的散列值。这个属性不仅适用于MD5散列算法,而且适用于许多其他算法其他的散列算法。你们的任务是设计一个实验来证明这个特性适用于MD5。
可以使用cat命令将两个文件(二进制文件或文本文件)连接为一个。以下命令将file2的内容连接到file1的内容,并将结果放在file3中。

$ cat file1 file2 > file3

  因为out1.bin和out2.bin的md5值相同,我们将它们连接到同一个out3.bin,理论上连接后生成的两个文件的md5值也相同。
  将out1.bin的内容连接到out3.bin的内容生成out13.bin,out2.bin的内容连接到out3.bin的内容生成out23.bin:
在这里插入图片描述

生成的out13.bin的md5和out23.bin的md5的值相同。

Task 3:生成两个具有相同MD5哈希值的可执行文件

  在这个任务中,您将得到以下C程序。您的工作是创建该程序的两个不同版本,以便它们的xyz数组的内容不同,但可执行文件的哈希值是相同的.

#include <stdio.h>
unsigned char xyz[200] = {
/* The actual contents of this array are up to you */
};
int main()
{
int i;
for (i=0; i<200; i++){
printf("%x", xyz[i]);
}
printf("\n");
}

  您可以选择在源代码级别工作,即生成上述C程序的两个版本,编译后,它们对应的可执行文件具有相同的MD5哈希值。然而,直接在二进制级别上工作可能更容易。你可以在xyz数组中放入一些随机值,将上面的代码编译为二进制。然后可以使用十六进制编辑器工具直接在二进制文件中修改xyz数组的内容。
  找到数组的内容存储在二进制文件中的位置并不容易。然而,如果我们用-些固定的值填充数组,我们可以很容易地在二进制文件中找到它们。例如,下面的 代码用0x41填充数组,这是字母A的ASCII值。在二进制中找到200个A并不困难。

unsigned char xyz[200] = {
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
... (omitted) ...
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
}

指导方针:从数组内部,我们可以找到两个位置,从那里我们可以将可执行文件分为三部分:前缀、128字节的区域和后缀。前缀的长度需要是64字节的倍数。图3演示了文件是如何划分的。
在这里插入图片描述

  我们可以在前缀上运行mdScollgen 来生成两个具有相同MD5散列值的输出文件。让我们使用P和Q来分别表示这两个输出的第二部分(每个有128字节)作为前缀后面的部分。因此,我们有以下:
      MD5 (prefix || P) = MD5 (prefix || Q)
根据MD5的属性,我们知道,如果在上述两个输出中添加相同的后缀,生成的数据也将具有相同的散列值。基本上,以下是适用于任何后缀的:
    MD5 (prefix || P || suffix) = MD5 (prefix || Q || suffix)
  因此,我们只需要使用P和Q来替换128字节的数组(在两个分界点之间),就可以创建两个具有相同哈希值的二进制程序。它们的结果是不同的,因为它们各自打印出具有不同内容的自己的数组。
  工具。您可以使用bless 来查看二进制可执行文件并找到数组的位置。为了划分二进制文件,我们可以使用一些工具来从特定位置划分文件。head和tail指令是非常有用的工具。你可以看说明书学习如何使用它们。下面我们举三个例子:

$ head -c 3200 a.out > prefix
$ tail -c 100 a.out > suffix
$ tail -c +3300 a.out > suffix

  上面的第一个命令保存a的 前3200字节到prefix文件。第二个命令保存a的最后100个字节到suffix文件。第三个命令将数据从第3300个字节到文件结束保存到suffix文件。通过这两个命令,我们可以从任何位置将一个二进制文件分割成若干块。
  如果我们需要将一些碎片粘在一起,我们可以使用cat命令。如果你用祝福来复制粘贴一块数据从一个二进制文件到另一个文件,该菜单项“编辑—>选择范围”是很方便的,因为你可以选择一块数据使用一个起点和一个范围,而不是手动计算有多少字节选中。
源代码:

#include <stdio.h>
unsigned char xyz[200] = {
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
};
int main()
{
int i;
for (i=0; i<200; i++){
printf("%x", xyz[i]);
}
printf("\n");
}

编译成二进制文件:
在这里插入图片描述

在二进制文件中找到xyz数组的位置:
在这里插入图片描述

  所以我们可以前1080h(4224)个字节作为前缀prefix文件,中间1080h到10C0h作为中间的128字节文件,后面第10C0h(4353)个字节到文件结束作为后缀suffix文件。
在这里插入图片描述

前缀prefix文件:
在这里插入图片描述

后缀suffix文件:
在这里插入图片描述

用前缀prefix文件上运行mdScollgen 来生成两个具有相同MD5散列值的输出:

md5collgen -p prefix -o out1.bin out2.bin
$ diff out1.bin out2.bin
$ md5sum out1.bin
$ md5sum out2.bin

在这里插入图片描述

  这时候out1.bin和out2.bin,就是由前缀prefix文件加上两个不同的128字节数据生成的具有相同md5值的文件:
  MD5 (prefix || P) = MD5 (out1.bin) = MD5 (out2.bin) = MD5 (prefix || Q)
我们再把后缀文件加上:在这里插入图片描述

得到两个可执行文件out1和out2,运行它们输出的字符串不同:
在这里插入图片描述

但是它们的MD5值相同。
MD5 (prefix || P || suffix) = MD5 (out1.bin || suffix)= MD5 (out1) = MD5 (out2) = MD5 (out2.bin || suffix) = MD5 (prefix || Q || suffix)
  其实,现在的两个MD5的相同的可执行文件和原来的二进制可执行文件,只是中间的128字节数据不同而已:
在这里插入图片描述
在这里插入图片描述

Task 4:使两个程序行为不同

  在前面的任务中,我们成功地创建了两个具有相同MD5散列的程序,但是它们的行为不同。然而,它们的区别仅仅在于打印出来的数据;它们仍然执行相同的指令序列。在这项任务中,我们希望实现更有意义更有意义的事情。
  假设您已经创建了一个做有益事情的软件。您将软件发送到一个可信任的权威机构进行认证。权威机构对您的软件进行全面的测试,并得出结论,您的软件确实在做有益的事情。权威机构会给你颁发-份证书,证明你的程序是正确的。为了防止您在获得证书后更改程序,您的程序的MD5哈希值也包含在证书中;证书是由权威机构签名的,因此您不能更改证书或程序上的任何内容而不使签名无效。
  您希望通过权威机构认证您的恶意软件,但是如果您只是将恶意软件发送给权威机构,那么您实现这一目标的机会为零。但是,您已经注意到,该机构使用MD5来生成散列值。你有主意了。你计划准备两个不同的程序。一个程序总是执行良性指令并做有益的事情,而另一个程序则执行恶意指令并造成损害。您可以找到一种方法使这两个程序共享相同的MD5散列值。
  然后将良性版本发送给权威机构进行认证。由于这个版本做了有益的事情,它将通过认证,您将获得一个包含良性程序的散列值的证书。由于您的恶意程序具有相同的哈希值,因此此证书对您的恶意程序也有效。因此,您已经成功地为您的恶意程序获得了有效的证书。如果其他人信任权威机构颁发的证书,他们就会下载您的恶意程序。
  这项任务的目的是发动上述攻击。也就是说,你需要创建两个共享相同MD5散列的程序。然而,一个程序将始终执行良性指令,而另一个程序将执行恶意指令。在你的工作中,执行什么良性/恶性指令并不重要;这足以证明这两个程序执行的指令是不同的。

指导方针:创建两个产生相同MD5散列值的完全不同的程序相当困难。md5collgen生成的两个hash-collision程序需要共享同一个前缀;此外,正如我们从前面的任务中可以看到的,如果我们需要向md5collgen生成的输出添加一些有意义的后缀,那么添加到两个程序的后缀也需要相同。这些是我们使用的MD5碰撞生成程序的限制。虽然有其他更复杂和更高级的工具,可以提升的一些局限性,如接受两种不同的前缀[2],它们需要更多的计算能力,所以它们不在这个实验室的研究范围之内。我们需要找到在限制范围内生成两个不同程序的方法
  有很多方法可以实现上述目标。我们提供一种方法作为参考,但鼓励学生提出自己的想法。老师可能会考虑奖励学生自己的想法。在我们的方法中,我们创建两个数组X和Y。我们比较这两个数组的内容;如果他们都是一样的,执行的是良性代码;否则,将执行恶意代码。看到下面的伪代码:

Array X;
Array Y;
main()
{
if(X’s contents and Y’s contents are the same)
run benign code;
else
run malicious code;
return;
}

  我们可以用一些值初始化数组X和Y,这些值可以帮助我们在可执行二进制文件中找到它们的位置。我们的工作是更改这两个数组的内容,这样就可以生成具有相同MD5散列的两个不同版本。在一个版本中,X和Y的内容是相同的,所以良性代码执行;在另一个版本中,X和Y的内容不同,所以恶意代码被执行。我们可以使用类似于Task3中使用的技术来实现这个目标。图4演示了程序的两个版本。
在这里插入图片描述

  从图4可知,只要P和Q相应地生成,这两个二进制文件具有相同的MD5哈希值。在第一个版本中,我们使数组X和Y的内容相同,而在第二个版本中,我们使它们的内容不同。因此,我们唯一需要更改的是这两个数组的内容,而不需要更改程序的逻辑。
我们先按照上面的思路,写一个比较X和Y数组的代码task4.c:

#include <stdio.h>
#include <string.h>
unsigned char X[200] = {
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
};
unsigned char Y[200] = {
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
};
int main()
{
	//大于返回正数,小于返回负数
	if (strcmp(X, Y)){
		printf("这是一个恶性程序\n");
	}
	//相等则返回0
	else {
		printf("这是一个良性程序\n");
	}
}

编译成二进制可执行程序task4:
在这里插入图片描述

打开二进制可执行程序task4,找到X数组的位置:
在这里插入图片描述

把前1080h(4224)个字节的数组取出来作为prefix前缀文件:
head -c 4224 task4 > prefix
在这里插入图片描述

再由prefix前缀文件用md5collgen生成两个MD5值相同文件:
在这里插入图片描述

得到的out1.bin和out2.bin,把它们最后128字节的数据作为X和Y数组的值:
在这里插入图片描述

先把out1.bin的尾缀128字节的数据填入可执行程序task4的X和Y数组,此时X和Y数组相等,即可得到一个良性的程序task4-1:
在这里插入图片描述

  再把out1.bin的尾缀128字节的数据填入Y数组,out2.bin的尾缀128字节的数据填入X数组(不要把X和Y数组弄反了),此时X和Y数组不相等,即可得到一个良性的程序task4-2:
在这里插入图片描述

且良性程序task4-1和恶性程序task4-2的MD5值相等:
在这里插入图片描述

  其实良性程序task4-1和恶性程序task4-2只是X数组中间的128字节不同(是out1.bin和out2.bin的尾缀128字节),Y数组中间的128字节相同(都是out1.bin的尾缀128字节,也可以都换成out2.bin的尾缀128字节):
在这里插入图片描述

实验完成!

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Postman的pre-request script脚本中,可以使用CryptoJS库来进行MD5加密。首先,你需要引入CryptoJS库。然后,你可以使用CryptoJS.MD5()方法来对需要加密的值进行加密。最后,使用.toString()方法将加密后的结果转换为字符串。下面是一个示例代码: ``` var CryptoJS = require('crypto-js'); // 需要加密的值 var value = 'your value'; // 进行MD5加密 var val_md5 = CryptoJS.MD5(value).toString(); // 将加密后的结果输出 console.log(val_md5); ``` 这段代码会将"value"进行MD5加密,并将加密后的结果输出。你可以根据自己的需求进行相应的修改和调整。 #### 引用[.reference_title] - *1* *2* [Postman进阶篇(三)-实战:pre-request script加密接口请求参数(AES、MD5)](https://blog.csdn.net/weixin_40883833/article/details/126593704)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [postman使用pre-request script计算md5](https://blog.csdn.net/ycwu314/article/details/97764264)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值