皮皮网

【shop开源源码】【熊猫管家源码】【java请假源码】哈希系统源码_哈希算法源码

2024-11-23 12:41:20 来源:sklearn源码怎么查看

1.如何在Ubuntu 22.04 / 20.04 LTS上安装Hashcat
2.String源码分析(1)--哈希篇
3.mimikatz源码分析-lsadump模块(注册表)
4.PostgreSQL-源码学习笔记(5)-索引
5.Hermes源码分析(二)——解析字节码
6.HashMap实现原理

哈希系统源码_哈希算法源码

如何在Ubuntu 22.04 / 20.04 LTS上安装Hashcat

       Hashcat是哈希哈希一款专为安全审计设计的高级密码恢复工具,支持各种哈希算法,系统具备广泛密码破解选项。源码源码最初为专有工具,算法但已转为开源。哈希哈希本文将指导您在Ubuntu Linux系统上安装Hashcat,系统shop开源源码适用于Ubuntu .、源码源码.及更高版本。算法安装前需确保系统具备互联网连接并具有sudo访问权限。哈希哈希

       开始系统更新

       在Ubuntu Linux上启动命令终端(快捷键Ctrl+Alt+T)。系统执行更新命令更新软件包。源码源码

       安装Hashcat

       Ubuntu默认系统存储库提供Hashcat所需软件包。算法执行命令安装Hashcat及其依赖项。哈希哈希

       检查版本确认安装

       安装完成后,系统检查版本以确认Hashcat已成功安装。源码源码

       源代码安装(可选)

       不想使用APT,希望安装最新Hashcat版本的用户可从源代码编译。步骤如下:

       安装开发工具

       克隆Hashcat Git存储库

       切换到Hashcat目录

       编译代码

       安装Hashcat

       编译完成后,执行命令安装Hashcat,系统将配置必需文件。

       重新加载会话

       检查版本以确保Hashcat正确安装。

       使用Hashcat

       运行命令查看可用选项。更多详细信息,请访问官方维基页面。

       其他文章

String源码分析(1)--哈希篇

       本文基于JDK1.8,从Java中==符号的使用开始,解释了它判断的是对象的内存地址而非内容是否相等。接着,通过分析String类的equals()方法实现,说明了在比较字符串时,应使用equals()而非==,因为equals()方法可以准确判断字符串内容是否相等。

       深入探讨了String类作为“值类”的特性,即它需要覆盖Object类的equals()方法,以满足比较字符串时逻辑上相等的需求。同时,强调了在覆盖equals()方法时也必须覆盖hashCode()方法,以确保基于散列的集合(如HashMap、HashSet和Hashtable)可以正常工作。解释了哈希码(hashcode)在将不同的输入映射成唯一值中的作用,以及它与字符串内容的熊猫管家源码关系。

       在分析String类的hashcode()方法时,介绍了计算哈希值的公式,包括使用这个奇素数的原因,以及其在计算性能上的优势。进一步探讨了哈希碰撞的概念及其产生的影响,提出了防止哈希碰撞的有效方法之一是扩大哈希值的取值空间,并介绍了生日攻击这一概念,解释了它如何在哈希空间不足够大时制造碰撞。

       最后,总结了哈希碰撞与散列表性能的关系,以及在满足安全与成本之间找到平衡的重要性。提出了确保哈希值的最短长度的考虑因素,并提醒读者在理解和学习JDK源码时,可以关注相关公众号以获取更多源码分析文章。

mimikatz源码分析-lsadump模块(注册表)

       mimikatz是一款内网渗透中的强大工具,本文将深入分析其lsadump模块中的sam部分,探索如何从注册表获取用户哈希。

       首先,简要了解一下Windows注册表hive文件的结构。hive文件结构类似于PE文件,包括文件头和多个节区,每个节区又有节区头和巢室。其中,巢箱由HBASE_BLOCK表示,巢室由BIN和CELL表示,整体结构被称为“储巢”。通过分析hive文件的结构图,可以更直观地理解其内部组织。

       在解析过程中,需要关注的关键部分包括块的签名(regf)和节区的签名(hbin)。这些签名对于定位和解析注册表中的数据至关重要。

       接下来,深入解析mimikatz的解析流程。在具备sam文件和system文件的情况下,主要分为以下步骤:获取注册表system的句柄、读取计算机名和解密密钥、获取注册表sam的句柄以及读取用户名和用户哈希。若无sam文件和system文件,mimikatz将直接通过官方API读取本地机器的注册表。

       在mimikatz中,java请假源码会定义几个关键结构体,包括用于标识操作的注册表对象和内容的结构体(PKULL_M_REGISTRY_HANDLE)以及注册表文件句柄结构体(HKULL_M_REGISTRY_HANDLE)。这些结构体包含了文件映射句柄、映射到调用进程地址空间的位置、巢箱的起始位置以及用于查找子键和子键值的键巢室。

       在获取注册表“句柄”后,接下来的任务是获取计算机名和解密密钥。密钥位于HKLM\SYSTEM\ControlSet\Current\Control\LSA,通过查找键值,将其转换为四个字节的密钥数据。利用这个密钥数据,mimikatz能够解析出最终的密钥。

       对于sam文件和system文件的操作,主要涉及文件映射到内存的过程,通过Windows API(CreateFileMapping和MapViewOfFile)实现。这些API使得mimikatz能够在不占用大量系统资源的情况下,方便地处理大文件。

       在获取了注册表系统和sam的句柄后,mimikatz会进一步解析注册表以获取计算机名和密钥。对于密钥的获取,mimikatz通过遍历注册表项,定位到特定的键值,并通过转换宽字符为字节序列,最终组装出密钥数据。

       接着,解析过程继续进行,获取用户名和用户哈希。在解析sam键时,mimikatz首先会获取SID,然后遍历HKLM\SAM\Domains\Account\Users,解析获取用户名及其对应的哈希。解析流程涉及多个步骤,包括定位samKey、获取用户名和用户哈希,以及使用samKey解密哈希数据。

       对于samKey的获取,mimikatz需要解密加密的数据,使用syskey作为解密密钥。解密过程根据加密算法(rc4或aes)有所不同,但在最终阶段,wps源码 qtmimikatz会调用系统函数对数据进行解密,从而获取用户哈希。

       在完成用户哈希的解析后,mimikatz还提供了一个额外的功能:获取SupplementalCreds。这个功能可以解析并解密获取对应用户的SupplementalCredentials属性,包括明文密码及哈希值,为用户提供更全面的哈希信息。

       综上所述,mimikatz通过解析注册表,实现了从系统中获取用户哈希的高效功能,为内网渗透提供了强大的工具支持。通过深入理解其解析流程和关键结构体的定义,可以更好地掌握如何利用mimikatz进行深入的安全分析和取证工作。

PostgreSQL-源码学习笔记(5)-索引

       索引是数据库中的关键结构,它加速了查询速度,尽管会增加内存和维护成本,但效益通常显著。在PG中,索引类型丰富多样,包括B-Tree、Hash、GIST、SP-GIST、GIN和BGIN。所有索引本质上都是独立的数据结构,与数据表并存。

       查询时,没有索引会导致全表扫描,效率低下。创建索引可以快速定位满足条件的元组,显著提升查询性能。PG中的索引操作函数,如pg_am中的注册,为上层模块提供了一致的接口,这些函数封装在IndexAmRoutine和IndexScanDesc中。

       B-Tree索引采用Lehman和Yao的算法,每个非根节点有兄弟指针,页面包含"high key",用于快速扫描。PG的insight看源码B-Tree构建和维护流程涉及BTBuildState、spool、元页信息等结构,包括创建、插入、扫描等操作。

       哈希索引在硬盘上实现,支持故障恢复。它的页面结构复杂,包括元页、桶页、溢出页和位图页。插入和扫描索引元组时,需要动态管理元页缓存以提高效率。

       GiST和GIN索引提供了更大的灵活性,支持用户自定义索引方法。GiST适用于通用搜索,而GIN专为复合值索引设计,支持全文搜索。它们在创建时需要实现特定的访问方法和函数。

       尽管索引维护有成本,但总体上,它们对提高查询速度的价值不可忽视。了解并有效利用索引是数据库优化的重要环节。

Hermes源码分析(二)——解析字节码

        前面一节 讲到字节码序列化为二进制是有固定的格式的,这里我们分析一下源码里面是怎么处理的

        这里可以看到首先写入的是魔数,他的值为

        对应的二进制见下图,注意是小端字节序

        第二项是字节码的版本,笔者的版本是,也即 上图中的4a

        第三项是源码的hash,这里采用的是SHA1算法,生成的哈希值是位,因此占用了个字节

        第四项是文件长度,这个字段是位的,也就是下图中的为0aa,转换成十进制就是,实际文件大小也是这么多

        后面的字段类似,就不一一分析了,头部所有字段的类型都可以在BytecodeFileHeader.h中看到,Hermes按照既定的内存布局把字段写入后再序列化,就得到了我们看到的字节码文件。

        这里写入的数据很多,以函数头的写入为例,我们调用了visitFunctionHeader方法,并通过byteCodeModule拿到函数的签名,将其写入函数表(存疑,在实际的文件中并没有看到这一部分)。注意这些数据必须按顺序写入,因为读出的时候也是按对应顺序来的。

        我们知道react-native 在加载字节码的时候需要调用hermes的prepareJavaScript方法, 那这个方法做了些什么事呢?

        这里做了两件事情:

        1. 判断是否是字节码,如果是则调用createBCProviderFromBuffer,否则调用createBCProviderFromSrc,我们这里只关注createBCProviderFromBuffer

        2.通过BCProviderFromBuffer的构造方法得到文件头和函数头的信息(populateFromBuffer方法),下面是这个方法的实现。

        BytecodeFileFields的populateFromBuffer方法也是一个模版方法,注意这里调用populateFromBuffer方法的是一个 ConstBytecodeFileFields对象,他代表的是不可变的字节码字段。

        细心的读者会发现这里也有visitFunctionHeaders方法, 这里主要为了复用visitBytecodeSegmentsInOrder的逻辑,把populator当作一个visitor来按顺序读取buffer的内容,并提前加载到BytecodeFileFields里面,以减少后面执行字节码时解析的时间。

        Hermes引擎在读取了字节码之后会通过解析BytecodeFileHeader这个结构体中的字段来获取一些关键信息,例如bundle是否是字节码格式,是否包含了函数,字节码的版本是否匹配等。注意这里我们只是解析了头部,没有解析整个字节码,后面执行字节码时才会解析剩余的部分。

        evaluatePreparedJavaScript这个方法,主要是调用了HermesRuntime的 runBytecode方法,这里hermesPrep时上一步解析头部时获取的BCProviderFromBuffer实例。

        runBytecode这个方法比较长,主要做了几件事情:

        这里说明一下,Domain是用于垃圾回收的运行时模块的代理, Domain被创建时是空的,并跟随着运行时模块进行传播, 在运行时模块的整个生命周期内都一直存在。在某个Domain下创建的所有函数都会保持着对这个Domain的强引用。当Domain被回收的时候,这个Domain下的所有函数都不能使用。

        未完待续。。。

HashMap实现原理

        HashMap在实际开发中用到的频率非常高,面试中也是热点。所以决定写一篇文章进行分析,希望对想看源码的人起到一些帮助,看之前需要对链表比较熟悉。

        以下都是我自己的理解,欢迎讨论,写的不好轻喷。

        HashMap中的数据结构为散列表,又名哈希表。在这里我会对散列表进行一个简单的介绍,在此之前我们需要先回顾一下 数组、链表的优缺点。

        数组和链表的优缺点取决于他们各自在内存中存储的模式,也就是直接使用顺序存储或链式存储导致的。无论是数组还是链表,都有明显的缺点。而在实际业务中,我们想要的往往是寻址、删除、插入性能都很好的数据结构,散列表就是这样一种结构,它巧妙的结合了数组与链表的优点,并将其缺点弱化(并不是完全消除)

        散列表的做法是将key映射到数组的某个下标,存取的时候通过key获取到下标(index)然后通过下标直接存取。速度极快,而将key映射到下标需要使用散列函数,又名哈希函数。说到哈希函数可能有人已经想到了,如何将key映射到数组的下标。

        图中计算下标使用到了以下两个函数:

        值得注意的是,下标并不是通过hash函数直接得到的,计算下标还要对hash值做index()处理。

        Ps:在散列表中,数组的格子叫做桶,下标叫做桶号,桶可以包含一个key-value对,为了方便理解,后文不会使用这两个名词。

        以下是哈希碰撞相关的说明:

        以下是下标冲突相关的说明:

        很多人认为哈希值的碰撞和下标冲突是同一个东西,其实不是的,它们的正确关系是这样的,hashCode发生碰撞,则下标一定冲突;而下标冲突,hashCode并不一定碰撞

        上文提到,在jdk1.8以前HashMap的实现是散列表 = 数组 + 链表,但是到目前为止我们还没有看到链表起到的作用。事实上,HashMap引入链表的用意就是解决下标冲突。

        下图是引入链表后的散列表:

        如上图所示,左边的竖条,是一个大小为的数组,其中存储的是链表的头结点,我们知道,拥有链表的头结点即可访问整个链表,所以认为这个数组中的每个下标都存储着一个链表。其具体做法是,如果发现下标冲突,则后插入的节点以链表的形式追加到前一个节点的后面。

        这种使用链表解决冲突的方法叫做:拉链法(又叫链地址法)。HashMap使用的就是拉链法,拉链法是冲突发生以后的解决方案。

        Q:有了拉链法,就不用担心发生冲突吗?

        A:并不是!由于冲突的节点会不停的在链表上追加,大量的冲突会导致单个链表过长,使查询性能降低。所以一个好的散列表的实现应该从源头上减少冲突发生的可能性,冲突发生的概率和哈希函数返回值的均匀程度有直接关系,得到的哈希值越均匀,冲突发生的可能性越小。为了使哈希值更均匀,HashMap内部单独实现了hash()方法。

        以上是散列表的存储结构,但是在被运用到HashMap中时还有其他需要注意的地方,这里会详细说明。

        现在我们清楚了散列表的存储结构,细心的人应该已经发现了一个问题:Java中数组的长度是固定的,无论哈希函数是否均匀,随着插入到散列表中数据的增多,在数组长度不变的情况下,链表的长度会不断增加。这会导致链表查询性能不佳的缺点出现在散列表上,从而使散列表失去原本的意义。为了解决这个问题,HashMap引入了扩容与负载因子。

        以下是和扩容相关的一些概念和解释:

        Ps:扩容要重新计算下标,扩容要重新计算下标,扩容要重新计算下标,因为下标的计算和数组长度有关,长度改变,下标也应当重新计算。

        在1.8及其以上的jdk版本中,HashMap又引入了红黑树。

        红黑树的引入被用于替换链表,上文说到,如果冲突过多,会导致链表过长,降低查询性能,均匀的hash函数能有效的缓解冲突过多,但是并不能完全避免。所以HashMap加入了另一种解决方案,在往链表后追加节点时,如果发现链表长度达到8,就会将链表转为红黑树,以此提升查询的性能。

hash / hashtable(linux kernel 哈希表)

       哈希表,或称为散列表,是一种高效的数据结构,因其插入和查找速度的优势而备受关注。然而,其空间利用率并不固定,需要权衡。让我们通过实例来深入理解它的作用和工作原理。

       想象一个场景:我们需要高效地存储和访问大量数据。首先,常规的数组方法,如普通数组和有序数组,虽然插入简单,但查找效率低,尤其是在数据量较大时。例如,查找可能需要对数千个元素进行比较。有序数组通过牺牲增删效率来提升查询,但数组空间固定且可能浪费大量资源。

       链表提供了更灵活的增删操作,但随机访问困难,适合数据频繁变动的情况。红黑树在查询和增删效率上表现优秀,但此处暂不讨论。庞大的数组虽然理论上能快速查找,但实际操作中难以实现,因为它需要预先预估并准备极大数据空间。

       这时,哈希表登场了。它利用哈希函数将数据映射到一个较小的数组中,即使存在冲突(不同数据映射到同一地址),通过链表解决,仍然能显著提升查找效率。例如,即使身份证号的哈希结果可能有重复,但实际冲突相对较少,通过链表链接,平均查找次数大大减少。

       使用哈希表包括简单的步骤:包含头文件,声明和初始化哈希表,添加节点,以及通过哈希键查找节点。在实际源码中,如Linux kernel的hash.h和hashtable.h文件,哈希表的初始化和操作都是基于这些步骤进行的。

       总结来说,哈希表在大数据场景中通过计算直接定位数据,显著提高效率,尤其是在数据量增大时。如果你对Linux kernel的哈希表实现感兴趣,可以关注我的专栏RTFSC,深入探讨更多源码细节。

HashMap实现原理一步一步分析(1-put方法源码整体过程)

       本文分享了HashMap内部的实现原理,重点解析了哈希(hash)、散列表(hash table)、哈希码(hashcode)以及hashCode()方法等基本概念。

       哈希(hash)是将任意长度的输入通过散列算法转换为固定长度输出的过程,建立一一对应关系。常见算法包括MD5加密和ASCII码表。

       散列表(hash table)是一种数据结构,通过关键码值映射到表中特定位置进行快速访问。

       哈希码(hashcode)是散列表中对象的存储位置标识,用于查找效率。

       Object类中的hashCode()方法用于获取对象的哈希码值,以在散列存储结构中确定对象存储地址。

       在存储字母时,使用哈希码值对数组大小取模以适应存储范围,防止哈希碰撞。

       HashMap在JDK1.7中使用数组+链表结构,而JDK1.8引入了红黑树以优化性能。

       HashMap内部数据结构包含数组和Entry对象,数组用于存储Entry对象,Entry对象用于存储键值对。

       在put方法中,首先判断数组是否为空并初始化,然后计算键的哈希码值对数组长度取模,用于定位存储位置。如果发生哈希碰撞,使用链表解决。

       本文详细介绍了HashMap的存储机制,包括数组+链表的实现方式,以及如何处理哈希碰撞。后续文章将继续深入探讨HashMap的其他特性,如数组长度的优化、多线程环境下的性能优化和红黑树的引入。

Redis7.0源码阅读:哈希表扩容、缩容以及rehash

       当哈希值相同发生冲突时,Redis 使用链表法解决,将冲突的键值对通过链表连接,但随着数据量增加,冲突加剧,查找效率降低。负载因子衡量冲突程度,负载因子越大,冲突越严重。为优化性能,Redis 需适时扩容,将新增键值对放入新哈希桶,减少冲突。

       扩容发生在 setCommand 部分,其中 dictKeyIndex 获取键值对索引,判断是否需要扩容。_dictExpandIfNeeded 函数执行扩容逻辑,条件包括:不在 rehash 过程中,哈希表初始大小为0时需扩容,或负载因子大于1且允许扩容或负载因子超过阈值。

       扩容大小依据当前键值对数量计算,如哈希表长度为4,实际有9个键值对,扩容至(最小的2的n次幂大于9)。子进程存在时,dict_can_resize 为0,反之为1。fork 子进程用于写时复制,确保持久化操作的稳定性。

       哈希表缩容由 tryResizeHashTables 判断负载因子是否小于0.1,条件满足则重新调整大小。此操作在数据库定时检查,且无子进程时执行。

       rehash 是为解决链式哈希效率问题,通过增加哈希桶数量分散存储,减少冲突。dictRehash 函数完成这一任务,移动键值对至新哈希表,使用位运算优化哈希计算。渐进式 rehash 通过分步操作,减少响应时间,适应不同负载情况。定时任务检测服务器空闲时,进行大步挪动哈希桶。

       在 rehash 过程中,数据查询首先在原始哈希表进行,若未找到,则在新哈希表中查找。rehash 完成后,哈希表结构调整,原始表指向新表,新表内容返回原始表,实现 rehash 结果的整合。

       综上所述,Redis 通过哈希表的扩容、缩容以及 rehash 动态调整哈希桶大小,优化查找效率,确保数据存储与检索的高效性。这不仅提高了 Redis 的性能,也为复杂数据存储与管理提供了有力支持。