微信小程序逆向分析

article/2025/5/14 20:55:22

文章目录

  • 微信小程序逆向分析
    • 行为监控
    • 分析文件特征
    • wxapkg解密思路
    • 重新监控
    • 解密分析
      • 尾部部分解密
        • 解密例程分析
        • 找到xorKey
      • 首部1024字节解密
        • 解密例程分析
        • AES_Key生成例程分析
        • 分组模式以及iv

微信小程序逆向分析

WeChatAppEx.exe 版本:2.0.6609.4

以融智云考学生端为例。

网上已经有关于微信小程序解密的非常优秀的文章,本着学习的目的便不参考相关内容。

笔者水平实在有限,如发现纰漏,还请读者不吝赐教。
如涉及侵权,请联系作者处理。

行为监控

工具:火绒剑

首先看看打开一个小程序微信做了点什么,对微信进行火绒行为监控。因为小程序最初在PC端运行,必然会相关文件在客户机上释放,所以我们主要关注微信的文件读写行为。

image-20230220190645549

注意到这里有类似文件释放的行为,在监控上访其实同样有读取此文件夹的行为,根据经验这其实就是一个简单的读取相关目录,发现没有相关程序逻辑文件后,主动请求服务器下载相关文件。

那我们的关注点来到\__APP__.wxapkg,根据前人的经验,这就是小程序的主要逻辑所在的地方。

其中可以监控到很多关于调用堆栈的信息,不过这些堆栈附近大概是文件释放相关逻辑,这并不是我们关注的重点。

image-20230220191050137

分析文件特征

我们用010Editor打开文件,任意一个二进制编辑器都可以。

image-20230220191351868

可以看到明显程序逻辑被加密那么我们关注点就来到了这个文件的解密操作。

wxapkg解密思路

那么有两种思路

  1. 很经典的思路,既然文件被加密,那么微信客户端装载此程序的时候必然要进行解密,那么必然要进行打开文件的操作,我们对CreateFile下断点,应该是可以找到打开文件的操作,记录打开的句柄,同时微信也需要对文件进行读取的操作。我们在ReadFile下条件断点,当传入的的句柄是我们获得的小程序文件的句柄时断下,调用堆栈附近应该就有相关解密的操作,这种操作可行性很大,但是相对比较麻烦,微信打开的文件很多,在CreateFile下断点可能比较麻烦。
  2. 如果微信使用的是比较常规的加密 算法,那么可以通过IDA的插件Findcrypt看看有没有比较明显的特征。

**需要注意到的是,在WeChat中并没用打开这个wxapkg的相关操作。那么斗胆猜测可能是微信重新启动一个加载器对wxapkg进行装载。**那么我们进行火绒剑全局监控,看看有没对wxapkg进行读取的操作。

重新监控

image-20230223081053737

可以观察到名为WeChatAppEx.exe对文件做了两次读取的操作,根据经验我们关注第二次读取,双击File_read操作,查看调用栈

image-20230223081312164

解密分析

跟随堆栈,我们在IDA和X64dbg中分别定位此位置。RVA:0x678353d

image-20230227192457113

可以看到此位置对文件进行了读取,我们在dbg中看看有没有文件的相关数据。附加到WeChatAppEx.exe,在对应位置下断点,并运行一个小程序。

image-20230227193059707

轻而易举的断下,并且我们观察到文件大小非常接近打开的加密文件大小,并且在堆栈中出现了相关文件信息。

我们步过查看readBuf内的数据。

image-20230227193456990image-20230227193548099

可以看到WeChatAppEx.exe读取了加密后的文件。那么我们不难理解WeChatAppEx.exe类似一个加载器,在运行时对文件进行解密装载。利用程序要对这一片内存进行读写的特征,我们对这篇内存区域下硬件访问断点(Xdbg的内存断点是针对内存页的,可能会断在奇怪的地方,可能是笔者不太会使用这种特性)

image-20230227194050235

可以看到在RVA:2784F7A处断下,比较奇怪的是此处对文件的前8字节赋值为0,不太能理解,索性我们对没有修改的内存再次下硬件访问断点(不要忘记卸载之前的断点)。

image-20230227194334132

再次断下时对之后的8个字节赋值为-1,同样比较难解,我们再次对剩余区域下硬件断点。

image-20230227194512906

再次在RVA:676C91E处断下,可以看到这里有对字符串操作的相关指令,根据movsb指令的功能

指令:                                          MOVSB, MOVSW, MOVSD描述:移动字符串数据,复制由ESI寄存器寻址的内存地址处的数据至EDI寻址的内存地址处。

拓展的,我们分别观察RSI与RDI指向的内存区域

image-20230227194922432

尾部部分解密

解密例程分析

可以看到RSI指向的内存中有非完整的加密文件的十六进制形式(前8字节,即V1MMWXß被忽略),有意思的是,复制操作的指针并没有指向文件头部,而是指向了距离除去V1MMWXß之后的1024字节之后,这里有分块加密的特征,但是为什么程序没有在解密前1024字节处停下呢,可能是笔者疏忽或者程序先解密尾部部分在解密首部,既然已经到这里,我们不妨顺藤摸瓜。

image-20230227195444637

可以看到正在向RDI中赋值数据,步过至字符串操作完成,我们再对这片内存区域下硬件访问断点。

之后再次在RVA:676C91E出断下,类似的,字符串操作完之后,我们再次对RDI下硬件访问断点。

再次运行之后再RVA:302772F处断下

image-20230227200017372

观察到我们下断点的内存区域已经出现了../image字样,这无疑是非常让人兴奋的,可能这就是文件解密的位置。事实确实如此,我们取消硬件断点,在上一步断下出的循环中循环几次简单分析就可以确定,这确实是一个解密点,而且是非常简单的异或解密。事实上,这一部分解密过程与微信图片解密相同。

image-20230227200537597

现在,我们找到了密文的1024字节之后部分的解密例程。我们默认忽略前8字节的处理,读者可自行分析,装载器并没有对前8字节做过多处理,在解密过程中只是简单的忽略。

找到xorKey

那么我们rbp所对应的秘钥0x34从何而来呢,追踪异或Key使我们接下来要做的事情。

有请尊敬的IDA先生,我们在IDA转到RVA:302772A,即异或解密位置追踪Key从何而来。

image-20230227201450775

根据分析,a3即是xorKey,至于a3*0x1010101010… 目的是用int8类型的值a3填满rbp至8个字节,进行8个字节分组异或。我们对a3进行简单的重命名—>xorKey_

image-20230227201804254

可以看到xorKey作为参数被传入(为提高辨识度,笔者对此函数进行简单的重命名)

image-20230227201934770

查看对此函数的引用,有两个运行时调用,还有一个直接调用,处于防止跟飞情况,我们对此函数头下断来找到调用点。

image-20230227202307226

文件再次断下,并在堆栈中回溯,我们来到调用点RVA:302759B

在IDA中我们了解到xorKey在异或解密函数ContextDecode中作为第三个参数传递,且类型为int8,根据fastcall调用约定,我们关注寄存器R8:000000000014EE34,最后一个字节,即0x34。他是怎么来的呢,我们向上分析

VA:00007FF632C97589处对r8最后一个字节进行了赋值,我们看[rax+rcx-0x2]是什么。

image-20230227203353743

可以看到rcx指向一个字符串,实际上这是微信小程序的ID,即AppID,进行简单的分析,rax是AppID的长度,而减去0x2后,[rax+rcx-0x2]指向的是AppID字符串的倒数第二个字符,将字符所对应的ascii码赋值给r8,这样,我们xorKey就拿到了。我们在everything找搜索对应AppId:wxf2a0156c0235fc4c

image-20230227203857299

可以证实上面的说法。至此,尾部部分解密告一段落。

首部1024字节解密

解密例程分析

我们再次来到RVA:0x678353d上方的ReadFile处下断,因为根据之前分析,此处有全部密文出现,同样我们忽视前8字节,对剩余内存内容下硬件访问断点,尝试寻找前1024字节解密位置。

image-20230228074305148

重新在此处断下(RVA:676C91E),同之前分析,补过字符串操作之灵后,我们跟随目的地(RDI)内存区域,对其下硬件访问断点。

image-20230228095838590

再次在此处断下(RVA:676C91E)断下,重复上述步骤,在目的地地址下断。

运行之后再RVA:40DFE处断下

image-20230228100244971

这里就有比较令人兴奋的字段:the iv:16bytes,部分加密需要一个向量,我们不妨猜测,这里就是加密函数,我们在IDA中来到对应位置。

image-20230228100551868

之前笔者已经对一些变量进行分析并且重命名,所以看起来似乎一目了然,这些变量的命名,我们之后逐步分析但不是现在的关注的重点。

引起我们注意的是类似的汇编指令aesdeclast xmm2, xmm1,注意到字样“aes”就可以怀疑密文首部采用的是aes加密,事实上确实采用的是这用加密,从学习的角度,我们假设并不知情相关特征。

既然到了这一步,不妨运行看看相关内存区域有没有明文信息。

image-20230228101635112

运行若干步之后,我们在RSI所指内存区域中发现明文特征,这与之前分析尾部解密中得出的明文十分类似,至此可以确定,这一部分逻辑即是对前1024字节进行解密的逻辑。

那么我们下一步要解决的问题是:”这是什么加密“,以便我们能找出秘钥,自行写出解密脚本。

我们百度aesdeclast xmm2, xmm1,看看能不能收获一些有用的信息。

下面是来自于互联网的一些资料:

AESDECLAST — Perform Last Round of an AES Decryption Flow

Opcode/InstructionOp/En64/32-bit ModeCPUID Feature FlagDescription
66 0F 38 DF /r AESDECLAST xmm1, xmm2/m128RMV/VAESPerform the last round of an AES decryption flow, using the Equivalent Inverse Cipher, operating on a 128-bit data (state) from xmm1 with a 128-bit round key from xmm2/m128.
VEX.128.66.0F38.WIG DF /r VAESDECLAST xmm1, xmm2, xmm3/m128RVMV/VBoth AES and AVX flagsPerform the last round of an AES decryption flow, using the Equivalent Inverse Cipher, operating on a 128-bit data (state) from xmm2 with a 128-bit round key from xmm3/m128; store the result in xmm1.

Description ¶

This instruction performs the last round of the AES decryption flow using the Equivalent Inverse Cipher, with the round key from the second source operand, operating on a 128-bit data (state) from the first source operand, and store the result in the destination operand.

128-bit Legacy SSE version: The first source operand and the destination operand are the same and must be an XMM register. The second source operand can be an XMM register or a 128-bit memory location. Bits (MAXVL-1:128) of the corresponding YMM destination register remain unchanged.

VEX.128 encoded version: The first source operand and the destination operand are XMM registers. The second source operand can be an XMM register or a 128-bit memory location. Bits (MAXVL-1:128) of the destination YMM register are zeroed.

请注意描述中的加粗部分,其大概意思是aesdeclast xmm2, xmm1执行的是反向解密的最后一轮解密过程,xmm1是round Key(拓展秘钥,aes将用户设置的秘钥进行拓展以便于运算),而xmm2即是最后一轮解密的数据。

现在我们可以确定这一部分加密使用的是AES加密,我们正在分析的是其对应的解密部分。根据AES加密的对应的解密过程,最后一轮解密使用的round Key正是用户设定的秘钥,关于AES使用类似指令的介绍以及加解密的细节问题,笔者收集到一篇优质文章:

Intel AES-NI使用入门 - 被遺忘的海灘 | Nagi’s Blog (x-nagi.com)

AES_Key生成例程分析

我们再次来到RVA:40DFE处

结合引用文章的介绍,我们大概可以得出:image-20230228110101401

那么我们接下来的关注点放到了拓展秘钥缓冲区,我们跟随秘钥缓冲区的生成会进入到秘钥拓展例程,在那里,我们大概率可以拿到Key,我们在IDA中追踪秘钥缓冲区

image-20230228110451042

v33对应的是Rcx,而拓展秘钥缓冲区即keyArry来自于函数外。我们对此函数头下断进行栈回溯。

函数头:

image-20230228110948500

再次断下后(前几次断下并不能得到我们要的调用栈,因为相关参数中找不到密文缓冲区等特征),根据fastcall约定,秘钥应该是r9所指缓冲区,实际上,秘钥缓冲区最后十六个字节作为原始Key的一部分(16字节),即未拓展的Key,秘钥拓展例程通过原始Key进行秘钥拓展,不过不注意这个细节也没有关系,这在之后的分析中将会体现。

image-20230228111415930

我们回溯到RVA:2811EB5

image-20230228111830755

在此函数中,keyArry已经生成,那么我们继续栈回溯,来到VA:00007FF6444C1137

image-20230228112514947

[rcx+0x10]即是keyArry,同样分析此函数,发现keyArry同样作为参数传入此函数,那么我们继续进行调用栈回溯。

回退到第二次调用栈,我们来到VA:00007FF6444C1398,如下图

image-20230228134042986

同样的,[rcx+0x10]即是keyArry,同样是作为参数传递进来的,再次进行堆栈回溯,来到RVA:00000000027F15AB,如下图,这里再次进行了简单的转发,再次进行栈回溯。

image-20230228135636609

来到RVA:285B20C,如下图image-20230228135936531

我们所说的keyArry是aes实例化的一个对象,里面存储有拓展秘钥。再此函数进行简单分析后发现,key同样来自函数外通过参数传递进来。

image-20230228142716246

继续堆栈回溯-_-||,来到RVA:000000000285AE26

image-20230228143005750

继续回溯,来到RVA:000000000285AED8,同样是一个简单的转发,继续回溯,来到RVA:0000000003026BF2

如下图

image-20230228145203926

如图,[[v18]+0x8]指向秘钥,终于要计算秘钥了-_-||,本函数上方有对v18的相关操作,如下图

image-20230228145835411

其实看到‘salt’这几个字符,对秘钥拓展熟悉的朋友应该能马上反应过来这里应该就是拓展秘钥的地方了。我们进到函数里

如图

image-20230228153739226

这就非常明确了,我们百度Pbkdf2

PBKDF的全称是Password-Based Key Derivation Function,简单的说,PBKDF就是一个密码衍生的工具。既然有PBKDF2那么就肯定有PBKDF1,那么他们两个的区别是什么呢?PBKDF2是PKCS系列的标准之一,具体来说他是PKCS#5的2.0版本,同样被作为RFC 2898发布。它是PBKDF1的替代品,为什么会替代PBKDF1呢?那是因为PBKDF1只能生成160bits长度的key,在计算机性能快速发展的今天,已经不能够满足我们的加密需要了。所以被PBKDF2替换了。在2017年发布的RFC 8018(PKCS #5 v2.1)中,是建议是用PBKDF2作为密码hashing的标准。PBKDF2和PBKDF1主要是用来防止密码暴力破解的,所以在设计中加入了对算力的自动调整,从而抵御暴力破解的可能性。

PBKDF2的工作流程

PBKDF2实际上就是将伪散列函数PRF(pseudorandom function)应用到输入的密码、salt中,生成一个散列值,然后将这个散列值作为一个加密key,应用到后续的加密过程中,以此类推,将这个过程重复很多次,从而增加了密码破解的难度,这个过程也被称为是密码加强。

稍微阅读以上引用内容 ,对比此函数参数不难得出:

  1. 盐值:saltiest
  2. 秘钥:小程序ID
  3. 秘钥拓展算法:PBKDF2
  4. 迭代次数:1000
  5. 秘钥长度:256位

既然秘钥长度是256位,那么可以推测出加密算法是AES_256。

注意到的是,它的伪散列算法是可以替换的,那么我们下一步要找出的是它使用的是哪种散列算法

这里笔者简单使用js选几种常见的散列算法试一试

const crypto = require('crypto');let appid = "wxf2a0156c0235fc4c";crypto.pbkdf2(appid,"saltiest",1000,32,'sha1',(err, derivedKey) => { if (err) throw err; console.log("The password is ",derivedKey.toString('hex'));});

image-20230228155330855

对比拓展秘钥函数运行之后的返回值[[rax]+0x8]中的值:

image-20230228161415221

可以验证散列算法是‘sha1’,对应我们在分析过程中的拓展秘钥的最后字节部分。

00001D5A002CD188     3D9D6AB5E94DDDE8 èÝMéµj.= 
00001D5A002CD190     71122C7B6FFE09D6 Ö.þo{,.q 
00001D5A002CD198     C3981F7A8828924E N.(.z..Ã 
00001D5A002CD1A0     BD14C8D6E69FEA98 .ê.æÖÈ.½ 
00001D5A002CD1A8     3336977C3609F094 .ð.6|.63 
00001D5A002CD1B0     1969D6DC01305252 RR0.ÜÖi. 

至此,我们找到了秘钥的生成算法。

分组模式以及iv

分组模式以及iv的寻找相对简单,只要对AES加密流程以及几种加密模式的区别熟悉就可以在加密函数(RVA:0000000000040C30)中分析出加密模式以及向量。这里笔者不再赘述。

经过简单分析,总结之前分析成果,有如下清单:

除去文件头8个字节,剩余1024解密算法:秘钥算法:PBKDF2盐值:saltiest秘钥:小程序ID,wxf2a0156c0235fc4c摘要算法:sha1秘钥长度:32字节解密算法:aes-256-cbc模式初始化向量iv:74 68 65 20 69 76 3A 20 31 36 20 62 79 74 65 73 对应字符串:“the iv: 16 bytes” -_-||
1024字节之后的数据处理方式:解密方式:异或解密异或Key:微信appid字符串的第二个字符对应的ASCII码形式。

拿到解密出的文件后可以用相应的解包脚本进行解压,网上不乏解压脚本,遗憾的是笔者并没有找到能够彻底解压并且还原出微信开发者工具能够识别的对应各式的文件(微信开发者工具对js等的样式做了一层封装,想要能够调试源代码需要将解包后的文件还原成其能够识别的格式,网上确实有相关脚本,但大多比较老,微信开发工具对样式进行了更新,格式化出现了一些问题,笔者水平有限,就不去修复。)

下面给出不成熟的C++解密脚本

#include "PKCS7.h"
#include <openssl/evp.h>
#include<openssl/aes.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>
#include <iostream>
#include <string>
#include <fstream>
#include <filesystem>using namespace std;unsigned char iv[] = { 0x74,0x68,0x65,0x20,0x69,0x76,0x3A,0x20,0x31,0x36,0x20,0x62,0x79,0x74,0x65,0x73 };//iv
unsigned char recursive_keys[32] = { 0 };//计算AES秘钥
const unsigned char  salt[] = "saltiest";//盐值int main()
{string app_id("wxf2a0156c0235fc4c");/*cout << "Plz enter the AppID:" << endl;cin >> app_id;*///计算递归秘钥PKCS5_PBKDF2_HMAC_SHA1(app_id.c_str(),app_id.length(),salt,strlen((const char*)salt),1000,32, recursive_keys);//cout << recursive_keys << endl;string file_name("__APP__.wxapkg");/*cout << "Plz enter the name of the file you want to decrypt :" << endl;cin >> file_name;*///读取文件int file_size = std::filesystem::file_size(file_name);char* file_buf = new char[file_size] {0};fstream fp(file_name.c_str(),std::ios::in|ios::binary);if (!fp.is_open()){cout << "Sorry,please check that you entered the correct file name" << endl;delete[] file_buf;file_buf = nullptr;return 0;}fp.read(file_buf, file_size);fp.close();//AES解密前1024字节内容(忽略文件头6个字节)AES_KEY aes_key;AES_set_decrypt_key((const unsigned char*)recursive_keys, 256, &aes_key);AES_cbc_encrypt((const unsigned char*)file_buf+0x6, (unsigned char*)file_buf+0x6, 1024, &aes_key, iv, AES_DECRYPT);PKCS7_unPadding* padding_result = removePadding(file_buf + 0x6, 1024);//解除填充size_t diff = 1024 - padding_result->dataLengthWithoutPadding;//得到解除填充后与保持填充时明文的差值//1024字节之后的密文解密//找到异或Keychar xor_key = app_id.c_str()[app_id.length() - 2];for (int i = 0; i < file_size - 0x6 - 0x400-diff; ++i){file_buf[0x406 + i - diff] = file_buf[0x406 + i] ^ xor_key;}//将解密后的数据写入fstream fp_out(file_name+"_plaintext",ios::out | ios::binary);if (!fp_out.is_open()){cout << "File create failed." << endl;fp_out.close();delete[] file_buf;file_buf = nullptr;freeUnPaddingResult(padding_result);return 0;}fp_out.write(file_buf+0x6,file_size-0x6-diff);fp_out.close();cout << "The file decryption is successful." << endl;delete[] file_buf;file_buf = nullptr;freeUnPaddingResult(padding_result);return 0;
}

WeChatAppEx_2.0.6609.4下载:
链接:https://pan.baidu.com/s/1N1f6DwOiIoElt9m1aN4uSw?pwd=vp03
提取码:vp03
供学习使用


http://chatgpt.dhexx.cn/article/XiRNTJ0T.shtml

相关文章

小程序发展简史

2017年元月9日微信正式推出第一个版本的小程序以来&#xff0c;大众对小程序经历了“热情->失望->质疑->回归->井喷爆发”的几个阶段。无疑小程序是个划时代的应用。它免安装&#xff0c;轻巧、免卸载、多入口的特性&#xff0c;从一诞生并自带光环。目前大分部主流…

微信小程序复习题

文章目录 填空题选择题判断题分析题&#xff08;20&#xff09;分析代码显示效果 页面设计题&#xff08;40&#xff09; 填空题 微信小程序创始人是 张小龙 &#xff0c;英文缩写 Mini Program小程序是一种无需下载和无需安装即可使用的应用&#xff0c;它实现了应用“ 触手可…

小程序获取附近IBeacon设备

实现逻辑&#xff1a; 该功能实现需要使用以下API&#xff1a; wx.startBeaconDiscovery(OBJECT)&#xff1a;开始搜索附近的iBeacon设备 wx.stopBeaconDiscovery(OBJECT)&#xff1a;停止搜索附近的iBeacon设备 wx.onBeaconUpdate(CALLBACK)&#xff1a;监听 iBeacon 设备…

微信小程序面试题大全

1、简述微信小程序的相关文件类型&#xff1f; WXML 搭建页面的结构WXSS 页面样式文件js 逻辑处理&#xff0c;网络请求json 配置当前页面标题和引入组件等app.js 可以在里边监听生命周期函数、声明全局变量app.json 小程序的全局配置&#xff08;页面路径、网络超时时间、底部…

微信小程序常见问题汇总

1、如何避免微信小程序中 app.js中 onshow事件的n次触发的问题? 问题 在开发中&#xff0c;遇到了一个小难题&#xff0c;就是app.js中 onshow事件总是会因调用其它API而触发&#xff0c;例如:wx.chooseImage&#xff0c;wx.makephonecall、wx. previewImage等。 解决办法 目…

怪兽充电小程序

第一首先看中心点上有个小图标 实现方式&#xff0c;我们可以使用map 结合一个图片覆盖物实现&#xff0c;在结合定位 <map id"myMap" show-locationenable-poienable-building :latitude"latitude":longitude"longitude":markers"marke…

扫盲篇 | 你真的懂附近的小程序吗?

“附近的小程序”功能是指用户进入微信小程序界面以后,可以直接看到所在地周围5公里左右的所有“小程序”。 包括实体店,服务店,商场等,微信小程序上线之初就曾提及该功能,而它几乎成了零售领域最期待的一项功能。 所以许多行业人士指出,小程序会给零售行业发展带来巨大…

有哪些常见的微信小程序推广引流方法?

如何对小程序进行推广引流。只有如此&#xff0c;才能为小程序获取到更多忠实用户&#xff0c;使小程序实现更大的价值。今天就为大家介绍一下微信小程序常见有效的推广方式。 1、附近的小程序&#xff08;免费&#xff09; 在小程序后台&#xff0c;开通“附近的小程序”&am…

微信附近的人小程序怎么开(开通附近小程序的方法)

1、进入微信公众号平台进入&#xff0c;输入小程序账号和密码&#xff0c;点击登录&#xff1b; 2、在左侧菜单中找到“附近的小程序”&#xff0c;点击开通。&#xff08;个体小程序不支持开通&#xff09; 3、验证管理员身份后按照要求填写资料&#xff0c;点击定位&#xf…

C语言/C++初学 问题

编程及C/C初学者 FAQ 本文原为本人在论坛所发若干帖&#xff0c;意在集中解决新手学习C/C语言时将遭遇到的各类问题&#xff0c;网友反馈情况良好&#xff0c;集合修订后作为个人作品贴于此处。 本贴主要分析概念原理和解决方案&#xff0c;不讨论具体程序语法&#xff0c;立足…

matlab2c使用c++实现matlab函数系列教程-randint函数

全栈工程师开发手册 &#xff08;作者&#xff1a;栾鹏&#xff09; matlab2c动态链接库下载 matlab库函数大全 matlab2c基础教程 matlab2c开发全解教程 matlab2c调用方法&#xff1a; 1、下载动态链接库 2、将Matlab2c.dll拷贝到exe同目录下 3、将Matlab2c.h、Matlab2c.lib放…

MATLAB只randint函数

srandint(M,N,range); 生成MxN的矩阵&#xff0c;矩阵中元素的取值为小于range的整数。 M4; N3; range3; srandint(M,N,range) 注意&#xff1a; randi函数生成元素取值为1&#xff1a;M的N*range的矩阵。

python中randint_python中randint函数的用法是什么?_后端开发

php的数据库怎么安装?_后端开发 安装步骤:1、在官网上下载数据库软件,然后双击下载好的数据库软件,打开后点击右下角的“下一步”,选择第一个选项“我接受”;2、默认勾选所有插件;3、选择安装数据库位置,点击“安装”;4、点击“完成”,这时php数据库就安装成功了。 …

Random.Randint 函数--Numpy

Numpy.Random.Randint 函数功能&#xff1a; Return random integers from low (inclusive) to high (exclusive)。 Return random integers from the “discrete uniform” distribution of the specified dtype in the “half-open” interval [low, high). If high is None…

Random库中的8个函数

random库包括两类函数&#xff0c;常用共8个 基本随机函数&#xff1a;seed() 、random()&#xff1b;扩展随机函数&#xff1a;randint()、getrandbits()、uniform()、randrange()、choice()、shuffle() 基本随机函数&#xff1a; seed()函数&#xff1a;初始化给定的随机数…

maven下载安装及IDEA配置、使用maven导出项目jar包并部署到服务器上

目录 1.下载安装 2.增加maven镜像仓库和修改仓库下载位置 镜像配置 修改仓库下载位置 3.小试&#xff1a;在idea中创建一个新maven项目 4.IDEA上配置maven 5.maven导出项目jar包 6.导出的项目jar包部署到服务器上 1.下载安装 &#xff08;1&#xff09;进入下载地址Ma…

maven的下载安装配置教程

maven的下载安装配置教程&#xff08;详细图文&#xff09; **各有各的选择&#xff0c;这也是一种过程**想要实现一个优秀的项目&#xff0c;光靠自己一个码农是很难的&#xff0c;我们需要引入别人已经集成好的类包来帮助我们优化项目&#xff0c;这个时候就需要使用maven了。…

Maven 的下载安装教程

Maven 3.6.3 下载安装教程 笔者的环境&#xff1a; JDK 13.0.2 Maven 3.6.3 IntelliJ IDEA 2020.1.2 (Ultimate Edition) 在继续阅读本教程之前&#xff0c;需要先完成 JDK 的安装。关于 JDK 的安装&#xff0c;可见笔者的另一篇博客&#xff1a; Java 的下载安装教程&…

Maven的下载安装与使用(idea)

Maven是什么 Maven是一款服务于Java平台的自动化构建工具。Maven 作为 Java 项目管理工具&#xff0c;它不仅可以用作包管理&#xff0c;还有许多的插件&#xff0c;可以支持整个项目的开发、打包、测试及部署等一系列行为。 传统工程我们直按把jar包放置在项目中&#xff0c; …

maven下载安装配置远程本地仓库

一、简介 maven最主要体现在两个词上&#xff1a;项目和管理。maven给我们整个开发团队找出了一种能够更加科学的去管理我们项目的思想。maven通过使用配置文件的方式使得项目在管理和交接的过程中成本变得非常低。maven提出了一种叫做maven仓库的概念,使得我们可以将第三方和我…