PC微信逆向:破解聊天记录文件!

2023-11-15

作者:newx

链接:https://bbs.pediy.com/thread-251303.htm

在电子取证过程中,也会遇到提取PC版微信数据的情况,看雪、52破解和CSDN等网上的PC版微信数据库破解文章实在是太简略了,大多数只有结果没有过程。经过反复试验终于成功解密了数据库,现在把详细过程记录下来,希望大家不要继续在已经解决的问题上过度浪费时间,以便更投入地研究尚未解决的问题。

通过查阅资料得知,与安卓手机版微信的7位密码不同,PC版微信的密码是32字节(64位),加密算法没有说明,但是可以通过OllyDbg工具从内存中获取到这个密码,然后通过一段C++代码进行解密。

 首先下载OllyDbg 2.01汉化版,我用的版本如下图所示:


运行OllyDbg,然后运行PC版微信(需要下载客户端的,不是网页版)。先不要点击登录按钮。


切换到Ollydbg界面:


点击文件菜单,选择“附加”,在弹出的对话框中找到名称为WeChat的进程,其窗口名称为“登录”。然后点击“附加”。


附加成功后OllyDbg开始加载,成功加载后可以看到最上面OllyDbg后面有WeChat.exe的字样:


在查看菜单中选择“可执行模块”:


找到名称为WeChatWin的模块,双击选中。为了方便观察,在窗口菜单中选择水平平铺。在CPU窗口标题栏可以看到“模块WeChatWin”字样。


在插件中选择“StrFinder字符查找”中的“查找ASCII字符串”(注意如果下载的OllyDbg版本不对,可能没有相关插件,因此一定要找对版本),要稍微等一会儿,会出现搜索结果的窗口。


在此窗口点击鼠标右键,选择“Find”,在搜索框中输入“DBFactory::encryptDB”。


会自动定位在第一处,但我们需要的是第二处,即“encryptDB %s DBKey can’t be null”下面这一处。可以用鼠标点击滚动条向下,找到第二处,用鼠标双击此处。


 在CPU窗口中可以看到已经定位到了相应的位置。用鼠标点击滚动条向下翻。


下面第六行应该是TEST EDX,EDX,就是用来比对密码的汇编语言代码。在最前面地址位置(本文中是0F9712BA)双击设置断点(设置断点成功则地址会被标红,而且可以在断点窗口中看到设置成功的断点)

点击“运行”按钮(或者在调试菜单中选择“运行”),这时寄存器窗口中的EDX的值应该是00000000。

切换到微信登录页面,点击登录,然后到手机端确认登录。这是OllyDbg界面中的数据不断滚动,直到EDX不再为全0并且各个窗口内容停止滚动为止。


在EDX的值上面点击鼠标右键,在弹出的菜单里面选择“数据窗口中跟随”,则数据窗口中显示的就是EDX的内容。


图示中从0B946A80(这个数值是变化的,不但每台电脑不同,每次调试也可能完全不同)到0B946A9F共32个字节就是微信的加密密码,本图中就是:

“53E9BFB23B724195A2BC6EB5BFEB0610DC2164756B9B4279BA32157639A40BB1”

 

一共32个字节,共64位。

得到这个之后,就可以关闭OllyDbg了,微信也会自动被关闭。

接下来就是解密过程。在看雪、52破解等多个论坛中都有相关的C++源码,开始企图使用Dev-C++或者C-Free等轻量级IDE进行编译,也使用过Visual C++ 6.0绿色精简版,结果多次尝试出现各种错误,反复失败,最终不得已使用Visual Studio,并对代码进行了一定的修正,终于调试成功。

正好Visual Studio 2019刚刚发布直接到官方网站下载了社区版。

根据查到的资料,需要先安装openssl,为了省事直接下载了最新的Win64OpenSSL-1_1_1b,安装后发现各种报错,继续查找资料发现原来sqlcipher使用的是低版本的openssl,之后找到了一个Win64OpenSSL-1_0_2r也报错,最后发现还是官方这个直接解压缩的版本靠谱:

https://www.openssl.org/source/openssl-1.0.2r.tar.gz

把压缩包直接解压到任意目录,比如c:\openssl-1.0.2r

启动Visual Studio 2019社区版(估计Visual Studio 2008以后的都应该可以,懒得找就直接官网下载最新的吧)

在启动界面右下方选择“创建新项目”


滚动下拉条,在窗口中选择C++控制台应用:


       给项目随便起个名字,选择保存位置:


然后点击“创建”,即可完成新项目创建。生成默认的Hello World代码:


先要做好项目的基础配置,之前调试失败主要问题就出在这里了。

在项目菜单中最下面选择项目属性“dewechat属性”(这个跟设置的项目名称一致)

对话框最左上角的配置后面,可以选择配置的是Debug模式还是Release模式(Release模式不包含调试信息,编译完成的exe文件更小一些,但如果是自己用,这两个模式没有区别,配置了哪个,后面就要用哪个模式编译,否则会报错)

先选择C/C++下面的“常规”选项:


右边第一条是“附加包含目录”,点击右侧空白处。在下拉框里选择“编辑…”,在对话框中点击四个图标按钮最左侧的“新行”按钮,会生成一个空白行,点击右侧的“…”:


在弹出的对话框里选择刚刚安装的openssl目录(本文是c:\openssl-1.0.2r)中的include目录。


设置完成后如下:


然后选择左侧“链接器”下面的“常规”:


在中间位置,有一个“附加库目录”,点击右侧空白处,选择openssl目录下的lib目录,设置完成后如下:


最后点击链接器下面的“输入”:

右侧最上面有“附加依赖项”,默认已经有一些系统库,点击右侧内容,选择“编辑…”


这个没有增加新行的按钮,只能手工录入或者拷贝文件名进去,需要增加上图所示的两个库名称。

设置完成后如下:


现在所有的设置都OK了,可以把代码放进来编译了。

由于太多网站转载,而且很多有错漏,已经搞不清原始代码是哪位大神写的了,其中有一些已经被废弃的代码,根据系统报错提示进行了替换,另外做了一个主要的变化就是之前的代码是把数据库名写在变量中,但由于需要解密很多库,为了灵活,改为输入参数的方法,即在运行时带参数运行或者根据提示输入需要解密的数据库文件名。

using namespace std;
#include <Windows.h>
#include <iostream>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/hmac.h>


#undef _UNICODE
#define SQLITE_FILE_HEADER "SQLite format 3" 
#define IV_SIZE 16
#define HMAC_SHA1_SIZE 20
#define KEY_SIZE 32


#define SL3SIGNLEN 20


#ifndef ANDROID_WECHAT
#define DEFAULT_PAGESIZE 4096       //4048数据 + 16IV + 20 HMAC + 12
#define DEFAULT_ITER 64000
#else
#define NO_USE_HMAC_SHA1
#define DEFAULT_PAGESIZE 1024
#define DEFAULT_ITER 4000
#endif
//pc端密码是经过OllyDbg得到的32位pass。
unsigned char pass[] = { 0x53,0xE9,0xBF,0xB2,0x3B,0x72,0x41,0x95,0xA2,0xBC,0x6E,0xB5,0xBF,0xEB,0x06,0x10,0xDC,0x21,0x64,0x75,0x6B,0x9B,0x42,0x79,0xBA,0x32,0x15,0x76,0x39,0xA4,0x0B,0xB1 };
char dbfilename[50];
int Decryptdb();
int CheckKey();
int CheckAESKey();
int main(int argc, char* argv[])
{
    if (argc >= 2)    //第二个参数argv[1]是文件名
        strcpy_s(dbfilename, argv[1]);  //复制    
           //没有提供文件名,则提示用户输入
    else {
        cout << "请输入文件名:" << endl;
        cin >> dbfilename;
    }
    Decryptdb();
    return 0;
}


int Decryptdb()
{
    FILE* fpdb;
    fopen_s(&fpdb, dbfilename, "rb+");
    if (!fpdb)
    {
        printf("打开文件错!");
        getchar();
        return 0;
    }
    fseek(fpdb, 0, SEEK_END);
    long nFileSize = ftell(fpdb);
    fseek(fpdb, 0, SEEK_SET);
    unsigned char* pDbBuffer = new unsigned char[nFileSize];
    fread(pDbBuffer, 1, nFileSize, fpdb);
    fclose(fpdb);


    unsigned char salt[16] = { 0 };
    memcpy(salt, pDbBuffer, 16);


#ifndef NO_USE_HMAC_SHA1
    unsigned char mac_salt[16] = { 0 };
    memcpy(mac_salt, salt, 16);
    for (int i = 0; i < sizeof(salt); i++)
    {
        mac_salt[i] ^= 0x3a;
    }
#endif


    int reserve = IV_SIZE;      //校验码长度,PC端每4096字节有48字节
#ifndef NO_USE_HMAC_SHA1
    reserve += HMAC_SHA1_SIZE;
#endif
    reserve = ((reserve % AES_BLOCK_SIZE) == 0) ? reserve : ((reserve / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;


    unsigned char key[KEY_SIZE] = { 0 };
    unsigned char mac_key[KEY_SIZE] = { 0 };


    OpenSSL_add_all_algorithms();
    PKCS5_PBKDF2_HMAC_SHA1((const char*)pass, sizeof(pass), salt, sizeof(salt), DEFAULT_ITER, sizeof(key), key);
#ifndef NO_USE_HMAC_SHA1
    PKCS5_PBKDF2_HMAC_SHA1((const char*)key, sizeof(key), mac_salt, sizeof(mac_salt), 2, sizeof(mac_key), mac_key);
#endif


    unsigned char* pTemp = pDbBuffer;
    unsigned char pDecryptPerPageBuffer[DEFAULT_PAGESIZE];
    int nPage = 1;
    int offset = 16;
    while (pTemp < pDbBuffer + nFileSize)
    {
        printf("解密数据页:%d/%d \n", nPage, nFileSize / DEFAULT_PAGESIZE);


#ifndef NO_USE_HMAC_SHA1
        unsigned char hash_mac[HMAC_SHA1_SIZE] = { 0 };
        unsigned int hash_len = 0;
        HMAC_CTX hctx;
        HMAC_CTX_init(&hctx);
        HMAC_Init_ex(&hctx, mac_key, sizeof(mac_key), EVP_sha1(), NULL);
        HMAC_Update(&hctx, pTemp + offset, DEFAULT_PAGESIZE - reserve - offset + IV_SIZE);
        HMAC_Update(&hctx, (const unsigned char*)& nPage, sizeof(nPage));
        HMAC_Final(&hctx, hash_mac, &hash_len);
        HMAC_CTX_cleanup(&hctx);
        if (0 != memcmp(hash_mac, pTemp + DEFAULT_PAGESIZE - reserve + IV_SIZE, sizeof(hash_mac)))
        {
            printf("\n 哈希值错误! \n");
            getchar();
            return 0;
        }
#endif
        //
        if (nPage == 1)
        {
            memcpy(pDecryptPerPageBuffer, SQLITE_FILE_HEADER, offset);
        }


        EVP_CIPHER_CTX* ectx = EVP_CIPHER_CTX_new();
        EVP_CipherInit_ex(ectx, EVP_get_cipherbyname("aes-256-cbc"), NULL, NULL, NULL, 0);
        EVP_CIPHER_CTX_set_padding(ectx, 0);
        EVP_CipherInit_ex(ectx, NULL, NULL, key, pTemp + (DEFAULT_PAGESIZE - reserve), 0);


        int nDecryptLen = 0;
        int nTotal = 0;
        EVP_CipherUpdate(ectx, pDecryptPerPageBuffer + offset, &nDecryptLen, pTemp + offset, DEFAULT_PAGESIZE - reserve - offset);
        nTotal = nDecryptLen;
        EVP_CipherFinal_ex(ectx, pDecryptPerPageBuffer + offset + nDecryptLen, &nDecryptLen);
        nTotal += nDecryptLen;
        EVP_CIPHER_CTX_free(ectx);


        memcpy(pDecryptPerPageBuffer + DEFAULT_PAGESIZE - reserve, pTemp + DEFAULT_PAGESIZE - reserve, reserve);
        char decFile[1024] = { 0 };
        sprintf_s(decFile, "dec_%s", dbfilename);
        FILE * fp;
        fopen_s(&fp, decFile, "ab+");
        {
            fwrite(pDecryptPerPageBuffer, 1, DEFAULT_PAGESIZE, fp);
            fclose(fp);
        }


        nPage++;
        offset = 0;
        pTemp += DEFAULT_PAGESIZE;
    }
    printf("\n 解密成功! \n");
    return 0;
}

将之前默认的代码全部清除,将以上代码拷贝进去,保存。然后在工具条栏中选择是Debug还是Release模式,是x86还是x64(需要跟之前配置匹配,如果选了没配置的模式会报错。测试发现几个选项没有太大区别,建议默认),之后点击“本地windows调试器”(或者按F5键),如果前面的步骤操作都正确,应该可以完成编译并自动运行,弹出一个命令行窗口,提示需要输入文件名:


最下方显示了生成的exe文件路径,将这个文件拷贝到微信数据库所在的目录,一般是:

C:\Users\Administrator\Documents\WeChat Files\********\Msg

其中********位置为需要解密的微信id,目录内容如下:


如果要解密ChatMsg.db,则在命令行窗口输入指令dewechat ChatMsg.db回车即可。


解密成功后,会在目录中生成de_ChatMsg.db,用sqlite数据库管理软件打开即可。

本文主要是个验证过程,没有做什么突破工作,目前的解密只能算是半自动过程,密码算法部分的获得是下一步需要研究的内容,希望大家共同努力!


— 完 —

点这里????关注我,记得标星呀~

长按进入小程序,进行打卡签到小程序送书福利更新啦!
(更多精彩值得期待……)
鸿蒙最近热文:假如你来发明编程语言
互联网公司部门鄙视链!
一款神奇的极客工具,用了永无 Bug
社会内卷的真正原因:华为内部论坛的这篇雄文火了

2T技术资源大放送!包括但不限于:C/C++,Linux,Python,Java,人工智能,考研,软考,英语,等等。在公众号内回复「资源」,即可免费获取!回复「社群」,可以邀请你加入读者群!
❤️给个「在看」,是对我最大的支持❤️
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PC微信逆向:破解聊天记录文件! 的相关文章

  • 为什么Java中的文件名与公共类名相同? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 在Java中 文件名应该与文件名相同public class包含在该文件中 为什么这是一个限制 它有什么目的 Java 有一个有趣的方法 如果给
  • PC 相当于 Coda 吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Apache Commons VFS - 无法解析文件

    VFS 方法无法处理此 URI jboss server temp dir local outgoing配置在jboss beans xml这是决心 C Download jboss eap 5 1 1 server default tmp
  • 限制 JPQL 中的结果数量

    如何限制从数据库检索结果的数量 select e from Entity e I need only 10 results for instance 您可以尝试像这样给出 10 个要显式获取的结果 entityManager createQ
  • 为什么我的 @OneToMany 属性出现主键违规?

    我有一个实体 Entity public class Student GeneratedValue strategy GenerationType AUTO Id private long id OneToMany private Set
  • 为本地@ExceptionHandler编写JUnit测试

    我有以下控制器 class Controller ResponseStatus HttpStatus OK RequestMapping value verifyCert method RequestMethod GET public vo
  • 进程退出后 POSIX 名称信号量不会释放

    我正在尝试使用 POSIX 命名信号量进行跨进程同步 我注意到进程死亡或退出后 信号量仍然被系统打开 在进程 打开它 死亡或退出后是否有办法使其关闭 释放 早期的讨论在这里 当将信号量递减至零的进程崩溃时 如何恢复信号量 https sta
  • Java 中通用方法参数的 getClass()

    以下 Java 方法无法编译
  • java中的第三个布尔状态是什么?

    虽然我知道根据定义 布尔值仅包含两种状态 真或假 我想知道布尔值在用这些状态之一初始化之前有什么值 它默认为 false http java sun com docs books tutorial java nutsandbolts dat
  • SDK尚未初始化,请务必先调用FacebookSdk.sdkInitialize()

    我在实现 Facebook SDK 时遇到此错误 并且我tried https stackoverflow com questions 15490399 error inflating class com facebook widget l
  • 在片段之间切换时底部导航栏会向下推

    在我的活动中 我有一个底部导航栏和框架布局来显示片段 一切正常 但问题是当我开始按顺序从 1 4 移动时 底部导航栏保持在其位置 但当我突然从 4 跳到2 然后底部导航栏就会超出屏幕 当再次单击同一项目时 它就会回到正常位置 该视频将清楚地
  • 如何在启用嵌入时间戳和 LTV 的情况下签署 PDF?

    我正在尝试签署启用了时间戳和 LTV 的 pdf 以便它在 Adob e Reader 中显示如下 在英语中 这意味着 签名包含嵌入的时间戳 和 签名启用了 LTV 这是我正在使用的代码 PrivateKey pk get pk from
  • 应用程序中空指针异常[重复]

    这个问题在这里已经有答案了 我正在尝试在我的应用程序中实施应用程序内计费 我写了这段代码 public class Settings extends PreferenceFragment ServiceConnection mService
  • 从特定 JAR 文件读取资源(文件的重复路径)

    假设您有 jar1 和artifactId 动物园 jar2 和artifactId 动物 两个 jar 都有一个具有相同路径的资源文件 例如 animals animal txt 有什么方法可以从特定的 jar 中读取该文件吗 使用 ge
  • EnumDisplayDevices 与 WMI Win32_DesktopMonitor,如何检测活动监视器?

    对于我当前的 C 项目 我需要为在大量计算机上连接并处于活动状态的每个监视器检测一个唯一的字符串 研究指出了两种选择 使用 WMI 并查询 Win32 DesktopMonitor 以获取所有活动监视器 使用 PNPDeviceID 来唯一
  • 在java中创建一个XML树并将其转换为json对象

    我尝试创建也能够转换为 json 的树 但对于只有一个xpath 当我尝试实现多个 xpath 时 我无法获得所需的输出 这里我分享一下我的实现 private static Document addElemtbypath List
  • 设置 Firefox 配置文件以使用 Selenium 和 Java 自动下载文件

    我想使用 Selenium WebDriver 和 Java 验证文件下载 要下载的文件为 PDF 格式 当 WebDriver 单击 AUT 中的 下载 链接时 Firefox 将打开以下下载确认窗口 我希望 Firefox 自动下载文件
  • AES 密钥是随机的吗?

    AES 密钥可以通过此代码生成 KeyGenerator kgen KeyGenerator getInstance AES kgen init 128 but 如果我有一个 非常可靠 的生成随机数的方法 我可以这样使用它吗 SecureR
  • 如何让JComboBox中的内容居中显示?

    目前我有这个JComboBox 我怎样才能将其中的内容居中 String strs new String 15158133110 15158133124 15158133458 JComboBox com new JComboBox str
  • Swing:创建可拖动组件...?

    我在网上搜索了可拖动 Swing 组件的示例 但我发现示例不完整或不起作用 我需要的是一个摇摆组件那可以是dragged通过鼠标 在另一个组件内 被拖拽的时候 应该已经 改变它的位置 而不仅仅是 跳 到目的地 我很欣赏无需非标准 API 即

随机推荐

  • SpringBoot 如何实现多数据源

    SpringBoot 如何实现多数据源 第一步 配置yml spring datasource type com alibaba druid pool DruidDataSource datasource1 url jdbc mysql 1
  • vue毕业设计分享 100例 (五)

    文章目录 前言 题目1 基于SSM的婚纱摄影业务系统 br 题目2 基于SSM的家教网课学习平台 br 题目3 基于SSM的家庭美食食谱管理系统 br 题目4 基于SSM的驾校预约培训管理系统 br 题目5 基于SSM的教师评价考核管理系统
  • 远程登陆之SSH的简单用法及命令

    SSH简单使用 SSH的安装 启动服务器的SSH服务 SSH远程登陆 口令登陆 公钥登陆 配置别名 传输文件 SSH只是一种协议 存在多种实现 既有商业实现 也有开源实现 OpenSSH是一种免费开源实现 OpenSSH是用于使用SSH协议
  • zabbix监控硬件

    一 通过snmp监控 1 idrac上开启snmp服务 2 然后到zabbix server服务器上测试一下是否能get到数据 snmpget v 2c c 1 3 6 1 4 1 674 10892 2 1 1 2 0 3 添加主机 二
  • rabbitmq的发布确认和事务

    2019独角兽企业重金招聘Python工程师标准 gt gt gt confirm的工作机制 Confirms是增加的一个确认机制的类 继承自标准的AMQP 这个类只包含了两个方法 confirm select和confirm select
  • 读取dgn文件思路

    1 opendgn 2 sourceforge里面有dgn读取内容 3 dgndirect 4 DGNLib 5 Teigha 6 lt
  • ERROR: cannot launch node of type [turtlebot_teleop/turtlebot_teleop_key] 问题解决

    当遇到问题 采取方式为 也就是说先用 rospack find 命令找是否存在 不存在就安装 sudo apt get install ros kinetic XXX 从网上查需要安装哪些内容 转载于 https www cnblogs c
  • 使用U盘为虚拟机安装系统

    转载自点击打开链接http www cnblogs com happy xiaoxiao p 8010547 html 前提 使用虚拟机安装WIN8系统时 由于WIN8镜像文件大于4G无法使用虚拟安装 所以使用U盘安装 1 装有U盘启动的W
  • 点云高度归一化处理(附 matlab 代码)

    由于不同地物之间存在着高程的差异 为了去除地形起伏对点云数据高程值的影响 所以需要根据提取出的地面点进行点云归一化处理 这一步是很多算法的基础 可以提高后续点云分类或分割的准确度等 如下图所示 归一化的过程其实相对简单 遍历每一个非地面点
  • Simon‘s writting 全网最全笔记

    石墨文档写完上传的 格式有点乱 凑合着看 排班不重要 内容最重要 一键三连的朋友可以私信我要word pdf 图片 markdown 那个看得舒服看哪个 An IELTS training course Understand the tas
  • Visual Studio下安装C/C++图形库(easyx)2022版

    一 Easyx下载链接 EasyX Graphics Library for C 二 Visual Studio上安装Easyx 1 右击EasyX 20220901 exe 选择管理员身份运行 2 点击下一步 3 它会自动检测 根据自己需
  • python3 新式邮件写法 附件乱码 解决

    import sys import re import mimetypes import base64 import traceback from pathlib import PurePath from datetime import d
  • 经过几年和前端调接口,我把抓包调试摸透了,浏览器岂非我对手

    场景 我们在和前端对接接口的时候 前端都是根据后端提供的接口api swagger地址或者yapi 其他接口管理平台进行接口联调 mock一些测试数据调试 调好了然后在本地和后端联调接口 没有问题后再发测试环境 测试环境再发预发布 预发布通
  • 打工族必看!省钱订餐攻略,经本人亲测多日!

    这不是广告哦 不像其他平台一样需要扫码关注等等 我的常用平台是不需要关注的 只要领取即可使用 我已经在这个平台点外卖很久了 几个月了 平常我会在这个平台领取优惠券 和同事一起拼单下单 每个人能省下三四块钱 有时候多的话可以省下七八块钱 这个
  • DevEco studio 一直加载gradle

    在使用DevEco studio 时一直处于提示gradle的问题 该现象和之前的Androoid Studio类似一直去网络中请求下载指定的gradle的版本 此时类比Android Studio先将gradle版本下载下来 然后放置在指
  • snort 源码分析之模式匹配引擎

    snort是一款著名的开源IPS 其主页地址 snort 官网 更详细的介绍网上很多 可自行搜索了解 本博客主要介绍snort 2 9 5版本的模式匹配引擎的加载和匹配 模式匹配引擎主要使用多模式匹配算法和单模式匹配算法 先由多模式匹配算法
  • Javaweb网站用户注册登录实现小记

    用户注册登录过程主要分为几个步骤 1 前端页面设计 2 数据访问模型包 3 Servlet容器数据接收处理 4 跳转至页面 下面分步骤小记一下 供以后参考 整个实现环境 Eclipse Version 2018 09 4 9 0 Eclip
  • 【满分】【华为OD机试真题2023B卷 JAVA&JS】叠积木

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 叠积木 知识点哈希表 时间限制 1秒 内存限制 262144K 语言限制 不限 题目描述 有一堆长方体积木 它们的宽度和高度都相同 但长度不一 小橙想把这堆积木叠成一面墙 墙的每层可以
  • 1033 旧键盘打字 Python实现

    1033 旧键盘打字 20 20 分 旧键盘上坏了几个键 于是在敲一段文字的时候 对应的字符就不会出现 现在给出应该输入的一段文字 以及坏掉的那些键 打出的结果文字会是怎样 输入格式 输入在2行中分别给出坏掉的那些键 以及应该输入的文字 其
  • PC微信逆向:破解聊天记录文件!

    作者 newx 链接 https bbs pediy com thread 251303 htm 在电子取证过程中 也会遇到提取PC版微信数据的情况 看雪 52破解和CSDN等网上的PC版微信数据库破解文章实在是太简略了 大多数只有结果没有