ida81输入密码验证算法分析以及破解思路

本文分析了ida81对输入密码的验证流程,分别对输入密码到生成解密密钥、密码素材的生成过程以及文件数据的加密过程这三个流程进行分析,并尝试找一些可利用的破绽。很遗憾,由于水平有限,目前也只是有个思路未能完全实现,故分享出来抛砖引玉。

1. 密码验证算法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

proc m4ZQu {password LZQjH} {

    set ::maui::util::H6VeX ""

    set ::maui::util::EL0BW [string repeat \\0 32]

    package require tcltwofish

    package require sha256

    if {[string length $LZQjH] == 0} {

        error "Unable to initialize encryption - missing essential data"

    }

     

    //1.展开payload 获取相关参数

    if {[binary scan $LZQjH Ia16a32a64a32a* times iv passwordKey encryptedKey payloadIVsHash encryptedPayloadIVs] < 6} {

        error "Unable to initialize encryption - header missing or corrupt"

    }

    //2.使用输入的密码计算sha256,然后根据迭代次数times加密passwordkey,最后计算结果的sha256

    set iHcWR [a64bL $password $passwordKey $iv $times]

     

    //3.取上一步中的后32字节

    set BJvoG [string range [tcltwofish::decrypt $iHcWR $encryptedKey] 32 63]

     

    //4.使用上一步中的结果作为key 循环times/64次 解密encryptedPayloadIVs

    //这一步没有指定iv 实际过程为16个字节的0x00

    for {set 0} {$i < $times} {incr i 64} {

        set encryptedPayloadIVs [tcltwofish::decrypt $BJvoG $encryptedPayloadIVs]

    }

    //5.获取32字节后的数据

    set ZQpQw [string range $encryptedPayloadIVs 32 end]

    //6.计算上一步结果的sha256,和预置的hash比对,一致则密码正确

    if {[sha2::sha256 -bin $ZQpQw] != $payloadIVsHash} {

        maui::d_RUj "Invalid payload password"

    }

     

    //7.使用第五步中的结果作为后续选取iv的数据

    set ::maui::util::H6VeX $ZQpQw

    //8.使用第三步中的结果作为密钥

    set ::maui::util::EL0BW $BJvoG

}

在这个过程中,第一步需要的payload为4020字节,这是已知的。意味着可以获取到第六步中正确的hash结果。
然而,根据下面的帖子总结,ida的密码选取字符为58个,密码长度为14个字符,这个测试结果是非常大的。
破密行動: 以不尋常的角度破解 IDA Pro 偽隨機數 | DEVCORE 戴夫寇爾
[下载] ida 8.1-资源下载-看雪-安全社区|安全招聘|kanxue.com

而我在i9-13900K测试从随机生成输入密码到第六步验证hash整个过程,测试一个密码就需要0.045秒。所以手里有超算也不建议直接爆破。

2. 密码素材的生成过程

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

//根据输入密码生成payload

proc yOZ7q {password {times 16000}} {

        set ::maui::util::H6VeX ""

        set ::maui::util::EL0BW [string repeat \\0 32]

        package require tcltwofish

        package require sha256

         

        set BJvoG [qA4kM 32]

        set passwordKey [qA4kM 32]

        set ZQpQw [qA4kM [expr {16 * 256}]]

        set payloadIVsHash [sha2::sha256 -bin $ZQpQw]

        set encryptedPayloadIVs "[qA4kM 32]$ZQpQw"

        for {set 0} {$i < $times} {incr i 64} {

            set encryptedPayloadIVs [tcltwofish::encrypt $BJvoG $encryptedPayloadIVs]

        }

        set iv [qA4kM 16]

        set iHcWR [a64bL $password $passwordKey $iv $times]

         

        set encryptedKey [tcltwofish::encrypt $iHcWR "[qA4kM 32]$BJvoG"]

        set LZQjH [binary format Ia16a32a64a32a* $times $iv $passwordKey $encryptedKey $payloadIVsHash $encryptedPayloadIVs]

        set ::maui::util::H6VeX $ZQpQw

        set ::maui::util::EL0BW $BJvoG

         

        return $LZQjH

    }

//生成随机数据

 proc qA4kM {length} {

        set YKL8w ""

        if {[RLPut unix]} {

            foreach xML4B {/dev/urandom /dev/random} {

                if {[catch {

                    set WyLEv [open $xML4B r]

                    fconfigure $WyLEv -translation binary

                    set YKL8w [read $WyLEv $length]

                    close $WyLEv

                }]} {

                    catch {close $WyLEv}

                }  else  {

                    break

                }

            }

        }  else  {

         

        }

        if {[string length $YKL8w] != $length} {

            incr length -[string length $YKL8w]

            while {$length >= 2} {

                append YKL8w [binary format S [expr {int([maui::util::rand] * 0x10000)}]]

                incr length -2

            }

            if {$length > 0} {

                append YKL8w [binary format c [expr {int([maui::util::rand] * 0x100)}]]

            }

        }

        return $YKL8w

    }

    proc rand {} {

        if {[maui::util::RLPut "windows"] && [info commands ::bitrock::secure::rand_s] != ""} {

            if {[catch {

                set r [::bitrock::secure::rand_s]

            } V77Ls]} {

                maui::util::debug "failed to call rand_s: $V77Ls"

                set r [expr {rand()}]

            }

        else {

            set r [expr {rand()}]

        }

        return $r

    }

继续分析输入密码的时生成payload的算法,根据安装密码生成payload的过程中,很多数据包括最后解密数据用的密钥BJvoG也是随机生成的,如果这部分随机数生成流程能复现那也是可以破解的。仔细看随机数的生成,已经排除了以前的LCG随机数生成算法,换成了更安全的,前后状态无影响的方式,linux或unix下用/dev/random或者/dev/urandom,windows下调用rand_s。
rand_s | Microsoft Learn

3. 文件数据加密流程

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

proc MmyBM {compressionAlgorithm command data} {

        if {[catch {

            //1.压缩数据

            if {($compressionAlgorithm == "lzma") || ($compressionAlgorithm == "lzma-ultra") || ($compressionAlgorithm == "lzham") || ($compressionAlgorithm == "lzham-ultra")} {

                set data [eval [concat $command [list $data]]]

            }  else  {

                set data [vfs::zip -mode compress -nowrap 1 $data]

            }

            //2.1 前面添加四个字节的长度,然后末尾补全32的倍数

            //2.2 前面添加32字节的随机数据

            set data [qA4kM 32][UOijU $data 32

            //3.在H6VeX中截取16字节的iv

            set PG2JA [expr {int([maui::util::rand] * 0x100)}]

            set iv [string range $::maui::util::H6VeX [expr {$PG2JA * 16}] [expr {$PG2JA * 16 + 15}]]

            //4.计算crc32

            set hbA8n [format 0x%08x [expr {[zlib crc32 $data] & 0xffffffff}]]

             

            //5.使用EL0BW中的数据作为key 加密

            set data [tcltwofish::encrypt $::maui::util::EL0BW $data iv]

             

            //6. 前面填充四个字节的crc32以及选取iv的位置,共加了五个字节

            set YKL8w [binary format Ica* $hbA8n $PG2JA $data]

        } V77Ls]} {

            set ykaki $::errorCode

            set qXoNi $::errorInfo

            maui::util::debug "encryptPayload: error encrypting: $V77Ls"

            error $V77Ls $qXoNi $ykaki

        }

        return $YKL8w

    }

1

2

3

4

5

6

7

8

9

proc UOijU {data DeSRF} {

    //1. 将四字节的长度添加在数据前

    set data [binary format Ia* [string length $data] $data]

    //2. 计算末尾添加padding的长度

    set add [expr {($DeSRF - ([string length $data] % $DeSRF)) % $DeSRF}]

    //3. 生成随机padding并附加在末尾

    append data [qA4kM $add]

    return $data

}

再看看文件数据的加密流程。从上面的脚本中,可以看到加密前的数据结果为 32字节随机数据+4字节数据+$data+最后补全32字节的padding 然后使用twofish进行加密。而twofish是分组加密算法,所以加密过程就是下面这样的


通过在前面添加32字节的随机数据,猜测是为了避免明文攻击。因为很多文件前面都有固定字节的数据

比如sqlite3数据库的前16字节固定为SQLite format 3\x00,在ECB模式下,相同密钥加密任何sqlite3数据库的前16个字节都是一样的。所以衍生出了CBC模式,在每个分组加密之前用iv或者上一个密文分组异或明文以产生不一样的数据。

然而,这个例子中前面32个字节的随机数的使用却颇有点画蛇添足的味道。
首先,它不能掩盖明文数据或者阻止明文攻击(稍后提到),其次因为这32字节的加密数据,我们在后面进行密码分析的时候可以忽略了原本的初始iv,初始iv来自哪里,来自输入密码后进行的16000次twofish加密和256次twofish解密后生成的0x1000字节的encryptedPayloadIVs,而现在却可以跳过了,从而暴露了它的阿克琉斯之踵。根据密码算法,现在解密每一段文件数据时只需要从第三个分组的数据开始解密即可,输入iv来源于上一个分组的的密文(即第二个分组),输入的key对所有文件都是一样的(也就是本次要分析出来的目标)。

再回头说说有哪些明文,从脚本可知加密的第三个分组前四个字节为加密数据的长度。在安装过程中会生成installbuilder_installer_{random}.log文件,统计生成的文件数。

在hook解密函数的过程中也发现了同样数量的加密数据,而这些数据中最小长度为0x000012a0,最大为0x00040060。所以这1212个文件在相同的密钥解密之后的前四个字节肯定是
00 0x xx xx。如果能将每段加密数据对应到具体的文件,可能还会有更多的明文信息。

综上所述,根据解密的tcl安装脚本共分析了三种破解思路:
第一种,根据输入密码爆破,工作量太大,PC上几乎不可能成功。
第二种,随机数攻击。新版本的安装程序摒弃了LCG算法的使用,使用了更加安全的随机数生成方式。
第三种,根据部分明文信息和1212个样本数据爆破32字节密钥,爆破的过程中每次验证只需要一次twofish解密16个字节即可。再配合密码差分分析,可以减少一定的尝试次数。有熟悉angr的大佬也可以尝试一下形式化验证的方式去破解。

另外,ida安装脚本中的twofish算法来源于GitHub - rageworx/libtwofish: TwoFish encryption library for modern C++ (dev.in progress)
,但是作了一些修改。文末附带校正后的版本,可以直接用。另外还有调试时用的frida脚本。

 

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

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

相关文章

【C++】单例模式【两种实现方式】

目录 一、了解单例模式前的基础题 1、设计一个类&#xff0c;不能被拷贝 2、设计一个类&#xff0c;只能在堆上创建对象 3、设计一个类&#xff0c;只能在栈上创建对象 4、设计一个类&#xff0c;不能被继承 二、单例模式 1、单例模式的概念 2、单例模式的两种实现方式 …

20231112_DNS详解

DNS是实现域名与IP地址的映射。 1.映射图2.DNS查找顺序图3.DNS分类和地址4.如何清除缓存 1.映射图 图片来源于http://egonlin.com/。林海峰老师课件 2.DNS查找顺序图 3.DNS分类和地址 4.如何清除缓存

工业摄像机参数计算

在工业相机选型的时候有点懵&#xff0c;有一些参数都不知道咋计算的。有些概念也没有区分清楚。‘’ 靶面尺寸 CMOS 或者是 CCD 使用几分之几英寸来标注的时候&#xff0c;这个几分之几英寸计算的是什么尺寸&#xff1f; 一开始我以为这个计算的就是靶面的实际对角线的尺寸…

ASP.NETWeb开发(C#版)-day1-C#基础+实操

目录 .NET实操&#xff1a;创建项目执行 C#基础语法数据类型变量实操001_变量如何在一个解决方案 中创建另一个项目实操002结构实操003-if else实操004-多分支多行注释按钮实操&#xff1a;循环 面向对象基础如何在同一个项目下创建新的.cs文件实操-类的定义与访问实操-练习实操…

Qt 自定义按钮 区分点按与长按信号,适配触摸事件

Qt 自定义按钮 区分点按与长按信号 适配触摸事件 效果 使用示例 // 点按connect(ui.btnLeft, &JogButton::stepclicked, this, &MainWindow::btnLeft_clicked);// 长按开始connect(ui.btnLeft, &JogButton::continueOn, this, &MainWindow::slotJogLeftOn);//…

Clickhouse学习笔记(11)—— 数据一致性

使用合并树引擎时&#xff0c;无论是ReplacingMergeTree还是SummingMergeTree&#xff0c;都只能保证数据的最终一致性&#xff0c;因为数据的去重、聚合等操作会在数据合并的期间进行&#xff0c;而合并会在后台以一个不确定的时间进行&#xff0c;因此无法预先计划&#xff1…

c语言:用指针解决有关字符串等问题

题目1&#xff1a;将一个字符串str的内容颠倒过来&#xff0c;并输出。 数据范围&#xff1a;1≤len(str)≤10000 代码和思路&#xff1a; #include <stdio.h> #include<string.h> int main() {char str1[10000];gets(str1);//读取字符串内容char* p&str1[…

有源RS低通滤波

常用的滤波电路有无源滤波和有源滤波两大类。若滤波电路元件仅由无源元件&#xff08;电阻、电容、电感&#xff09;组成&#xff0c;则称为无源滤波电路。无源滤波的主要形式有电容滤波、电感滤波和复式滤波(包括倒L型、LC滤波、LCπ型滤波和RCπ型滤波等)。若滤波电路不仅有无…

从0开始python学习-32.pytest.mark()

目录 1. 用户自定义标记 1.1 注册标记​编辑 1.2 给测试用例打标记​编辑 1.3 运行标记的测试用例 1.4 运行多个标记的测试用例 1.5 运行指定标记以外的所有测试用例 2. 内置标签 2.1 skip &#xff1a;无条件跳过&#xff08;可使用在方法&#xff0c;类&#xff0c;模…

[vuex] unknown mutation type: SET_SOURCE

项目中使用了vuex&#xff0c;并且以模块的形式分好之后。在调用的时候出现了以上问题 /*当我们commit的时候要注意要加上模块的名字 user是模块名称&#xff0c;SET_SOURCE是user模块中定义的方法 正确写法&#xff1a;*/ this.$store.commit("user/SET_SOURCE", th…

火爆进行中的抖音双11好物节,巨量引擎助5大行业商家开启爆单之路!

抖音双11好物节目前正在火热进行中&#xff0c;进入爆发期&#xff0c;各大商家“好招”频出&#xff0c;都想要实现高速增长。依托“人群、货品、流量”三大优势&#xff0c;巨量引擎一直都是商家生意增长的给力伙伴&#xff0c;在今年的抖音双11好物节&#xff0c;巨量引擎就…

Conda executable is not found 三种问题解决

如果在PyCharm中配置Python解释器时显示“conda executable is not found”错误消息&#xff0c;这意味着PyCharm无法找到您的Conda可执行文件。您可以按照以下步骤解决此问题&#xff1a; 1.方法一 确认Conda已正确安装。请确保您已经正确安装了Anaconda或Miniconda&#xff…

华为ensp:vrrp双机热备负载均衡

现在接口ip都已经配置完了&#xff0c;直接去配置vrrp r1上192.168.1.100 作为主 192.168.2.100作为副 r2上192.168.1.199 作为副 192.168.2.100作为主 这样就实现了负载均衡&#xff0c;如果两个都正常运行时&#xff0c;r1作为1.1的网关&#xff0c;r2作为2.1网关…

Vue3+NodeJS 接入文心一言, 发布一个 VSCode 大模型问答插件

目录 一&#xff1a;首先明确插件开发方式 二&#xff1a;新建一个Vscode 插件项目 1. 官网教程地址 2. 一步一步来创建 3. 分析目录结构以及运行插件 三&#xff1a;新建一个Vue3 项目&#xff0c;在侧边栏中展示&#xff0c;实现vscode插件 <> vue项目 双向消息传…

“第六十六天”

这个我记得是有更优解的&#xff0c;不过还是明天发吧&#xff0c;明天想一想&#xff0c;看看能不能想起来 #include<string.h> int main() {char a[201] { 0 };char b[201] { 0 };scanf("%s %s", a, b);int na strlen(a);int nb strlen(b);int i 0, j …

【408】计算机学科专业基础 - 数据结构

数据结构知识 绪论 数据结构在学什么 如何用程序代码把现实世界的问题信息化 如何用计算机高效地处理这些信息从而创造价值 数据结构的基本概念 什么是数据&#xff1a; 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序…

css:两个行内块元素和图片垂直居中对齐

目录 两个行内块元素垂直居中对齐图片垂直居中问题图片和文字垂直居中对齐参考文章 两个行内块元素垂直居中对齐 先看一段代码&#xff1a; <style> .box {width: 200px;height: 200px;line-height: 200px;font-size: 20px;text-align: center;display: inline-block;b…

计算机毕业设计选题推荐-校园交流平台微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

【tgcalls】Instance接口的实例类的创建

tg 里有多个版本,因此设计了版本管理的map,每次可以选择一个版本进行实例创建这样,每个客户端就可以定制开发了。tg使用了c++20创建是要传递一个描述者,里面是上下文信息 G:\CDN\P2P-DEV\tdesktop-offical\Telegram\ThirdParty\tgcalls\tgcalls\Instance.cpp可以看到竟然是…

基于Qt 多线程(继承自QThread篇)

# 简介 我们写的一个应用程序,应用程序跑起来后一般情况下只有一个线程,但是可能也有特殊情况。比如我们前面章节写的例程都跑起来后只有一个线程,就是程序的主线程。线程内的操作都是顺序执行的。恩,顺序执行?试着想一下,我们的程序顺序执行,假设我们的用户界面点击有某…