当前位置: 首页 > news >正文

【吾爱】逆向实战crackme160破解记录(三)

前言

cm160已经第三篇了,做到了第七个cm(第五个被跳过了,之后有时间回头把这个做了)。
题目来源依旧是吾爱破解论坛上pk8900总结好的160个crackme,依旧只是做一下自己练习的记录,欢迎讨论学习,感谢吾爱论坛的各位大神。

程序本身无病毒,杀毒报错可无视,如果实在担心也可也用虚拟机练习

参考链接:
https://www.52pojie.cn/forum.php?mod=viewthread&tid=709699&extra=page=1&filter=author&orderby=dateline

Andrénalin.1

照例先检查下程序信息。
在这里插入图片描述
32位vb程序,没有加密壳,程序打开后只有一个输入框和ok按钮。随手输入后弹出来的错误提示,发现这语言有点看不懂,不知道是啥语言,那我们xdbg来看一下。
在这里插入图片描述
在这里插入图片描述

xdbg里面搜索字符串,发现了提示成功和失败的字符串,跟踪过去看一下具体的代码。
在这里插入图片描述

在这里插入图片描述
发现successful提示的上面有个je跳转,跳转后会提示输入失败的信息。所以把这个nop掉看看。
在这里插入图片描述

在这里插入图片描述
RiCHtiG !...nun weiter zu CrackMe 2!
翻译一下发现是德语的提示,直接给通过了。看来这个cm的逻辑还是挺简单的。简单在xdbg里面看一下,发现还有个字符串不知道用到哪了,而且使用的位置刚好在刚刚nop掉的判断的上面,测试了一下就发现是需要输入的key,那这个cm的判断逻辑就是固定值判断,密钥就是SynTaX 2oo1
在这里插入图片描述
在这里插入图片描述

Andrénalin.2

跟上面的题目是同一个作者,先检查文件,发现依旧是32位vb程序。

在这里插入图片描述
在这里插入图片描述

打开程序之后,发现这次的验证是需要name和key的,随手输入一下看一下报错的信息,感觉还是德文,待会再xdbg里面可以找一下。

在这里插入图片描述
然后拖进xdbg里面看一下。
在这里插入图片描述
在这里插入图片描述
所以这个RiCHTiG !就是正确的提示。
那跟踪过去看一下
在这里插入图片描述
发现上面的je跳转,在阻止代码进入到正确的提示内容。所以Nop掉看一下。

在这里插入图片描述

在这里插入图片描述
这样就cm破解成功了。当然这样还不够,我们看一下这个获取key的逻辑是什么。

在这里插入图片描述
je是同噶zf寄存器的值来判断的,上面有个test bx,bx会修改zf的值,bx不为零的时候就判断失败,程序不跳转。此处的 BX 值由MOV EBX, EAX(004022B7)传递而来,而 EAX 是函数 __vbaVarTstEq(变量相等性测试)的返回值。
所以猜测目的就是通过 __vbaVarTstEq 比较变量是否相等 → 结果存入 EAX/BX → 用 TEST+JE 判断比较结果是否为 0(即相等)。
那看一下这个__vbaVarTstEq 函数,是将ecxeax进行比较,所以得看eax和ecx的数据是怎么来的,这两个判断的话,肯定有一个是来自于用户输入的,所以得从用户输入的地方开始,一直到这里判断这一大段的代码进行逻辑分析。

这里找了一大圈,我对vb代码不是很熟悉,所以没找到哪里开始获取用户输入的数据,只好找个反编译工具静态分析一下。
用的是VB Decompiler,发现代码其实只有两个函数。
在这里插入图片描述

Private Sub Text2_Change() '4024F0Dim var_1C As Variantloc_00402553: var_18 = Text2.Textloc_00402587: ebx = (var_18 = vbNullString) + 1loc_0040259D: If (var_18 = vbNullString) + 1 = 0 Then GoTo loc_004025C3loc_004025AA: Set var_1C = (var_18 = vbNullString)loc_004025B7: Command1.Enabled = Falseloc_004025BF: If var_1C >= 0 Then GoTo loc_004025F7loc_004025C1: GoTo loc_004025E5loc_004025CE: Set var_1C = var_1Cloc_004025DB: Command1.Enabled = Trueloc_004025E3: If var_1C >= 0 Then GoTo loc_004025F7loc_004025E5: 'Referenced from: 004025C1loc_004025F1: var_1C = CheckObj(var_1C, var_00401DC8, 140)loc_004025F7: loc_0040260C: GoTo loc_00402621loc_00402620: Exit Subloc_00402621: 'Referenced from: 0040260C
End Sub

上面这个是获取输入框的代码
下面是核心验证的代码:

Private Sub Command1_Click() '401FF0loc_00402092: var_58 = Text2.Textloc_004020CA: var_44 = var_58loc_00402126: For var_24 = 1 To Len(var_44) Step 1loc_00402132: loc_00402134: If var_108 = 0 Then GoTo loc_004021D6loc_00402169: var_58 = CStr(Mid(var_44, CLng(var_24), 1))loc_00402176: var_B4 = Asc(var_58)loc_004021A0: var_34 = var_34 + Asc(var_58)loc_004021CB: Next var_24loc_004021D1: GoTo loc_00402132loc_004021D6: 'Referenced from: 00402134loc_00402204: var_34 = var_34 * 1234567890loc_00402276: var_58 = Text1.Textloc_00402298: var_64 = var_58loc_004022CB: If (var_58 = var_34) = 0 Then GoTo loc_00402391loc_004022D1: Beeploc_00402308: var_B4 = "RiCHTiG !"loc_00402327: var_A4 = "  RiCHTiG !!!!   ....  weiter mit dem Nächsten !!!"loc_00402374: var_54 = MsgBox("  RiCHTiG !!!!   ....  weiter mit dem Nächsten !!!", 48, "RiCHTiG !", 10, 10)loc_0040238C: GoTo loc_00402446loc_00402391: 'Referenced from: 004022CBloc_004023C2: var_B4 = "LEiDER Falsch !  "loc_004023E1: var_A4 = "Leider Falsch!   Nochmal veruschen ! Wenn Du es nicht schaffen solltest, schreib mir !  Andrenalin@gmx.net"loc_0040242E: var_54 = MsgBox("Leider Falsch!   Nochmal veruschen ! Wenn Du es nicht schaffen solltest, schreib mir !  Andrenalin@gmx.net", 16, "LEiDER Falsch !  ", 10, 10)loc_00402446: 'Referenced from: 0040238Cloc_00402459: GoTo loc_0040248Floc_0040248E: Exit Subloc_0040248F: 'Referenced from: 00402459loc_004024C0: GoTo loc_00esi
End Sub

也给出了汇编的源码,因为太长了这里就不贴全了。
在这里插入图片描述

分析一下逻辑是:

遍历输入文本的每个字符
ord() 函数获取字符的ASCII值(等效VB的 Asc())
累加所有ASCII值到 ascii_sum
将ASCII总和乘以固定常数 1234567890
将第4个和第9个字符使用字符【-】替代

这里发现反编译的vb代码和汇编语言存在出入,怀疑是反编译时把部分汇编源码给遗漏了,vb代码中缺失了字符【-】替代的逻辑,但是汇编里面有,这里是试了好几次发现还是不对之后,又重新去看了有汇编代码之后才发现的。最后汇编代码反正看出来了逻辑,就没去细究这个反编译的问题(毕竟用的反编译的软件也挺老了)

知道逻辑之后写个破解脚本


def generate_key(account):# 计算ASCII总和ascii_sum = sum(ord(c) for c in account)# 乘以常数 (64位浮点运算)total = ascii_sum * 1234567890.0# 转换为长整型字符串key_str = str(int(total))# 替换第4和第9位字符 (VB索引从1开始)if len(key_str) >= 4:key_str = key_str[:3] + '-' + key_str[4:]if len(key_str) >= 9:key_str = key_str[:8] + '-' + key_str[9:]return key_str# 测试示例
name = input("输入name:")
print(generate_key(name))  # 输出类似 "168-925802-460"

测试一下:
在这里插入图片描述
在这里插入图片描述
发现判断成功了。那么这个cm的判断逻辑也找了出来。可以接着做下一道题目了。

Andrénalin.3

依旧是Andrénalin作者的程序,接着查一下程序,依旧是32位vb程序,没有加密壳。

打开程序后发现只有一个key序列号的验证。
在这里插入图片描述
xdbg里面查找字符串,然后跟踪过去看一下代码,找到了提示成功的部分以及上面的je判断。
在这里插入图片描述

下个断点然后nop一下:
在这里插入图片描述
在这里插入图片描述
这样就直接成功了,但是依旧去看一下验证的逻辑。
上面发现一个怀疑是静态key的值kXy^rO|*yXo*m\\kMuOn*+,还以为跟第一个程序一样是静态key,就试了一下,结果不是,那接着反编译一下。
找到了反编译的vb代码:

Private Sub Command1_Click() '401E20loc_00401EC2: var_58 = Text1.Textloc_00401EFA: var_44 = var_58loc_00401F56: For var_24 = 1 To Len(var_44) Step 1loc_00401F68: loc_00401F6A: If var_104 = 0 Then GoTo loc_0040202Bloc_00401FA3: var_58 = CStr(Mid(var_44, CLng(var_24), 1))loc_00401FB0: Asc(var_58) = Asc(var_58) + 000Ahloc_00401FC4: var_84 = Chr$(Asc(var_58))loc_00401FED: var_34 = var_34 & Chr$(Asc(var_58))loc_00402020: Next var_24loc_00402026: GoTo loc_00401F68loc_0040202B: 'Referenced from: 00401F6Aloc_00402053: If (var_34 = "kXy^rO|*yXo*m\kMuOn*+") = 0 Then GoTo loc_00402119loc_00402059: Beeploc_00402090: var_B4 = "RiCHTiG !"loc_004020AF: var_A4 = "  RiCHTiG !!!!   ....  weiter mit dem Nächsten !!!"loc_004020FC: var_54 = MsgBox("  RiCHTiG !!!!   ....  weiter mit dem Nächsten !!!", 48, "RiCHTiG !", 10, 10)loc_00402114: GoTo loc_004021CEloc_00402119: 'Referenced from: 00402053loc_0040214A: var_B4 = "LEiDER Falsch !  "loc_00402169: var_A4 = "Leider Falsch!   Nochmal veruschen ! Wenn Du es nicht schaffen solltest, schreib mir !  Andrenalin@gmx.net"loc_004021B6: var_54 = MsgBox("Leider Falsch!   Nochmal veruschen ! Wenn Du es nicht schaffen solltest, schreib mir !  Andrenalin@gmx.net", 16, "LEiDER Falsch !  ", 10, 10)loc_004021CE: 'Referenced from: 00402114loc_004021E1: GoTo loc_00402217loc_00402216: Exit Subloc_00402217: 'Referenced from: 004021E1loc_00402248: GoTo loc_00esi
End Sub

有个第二题的经验,所以这个vb代码感觉不是特别可信,还得结合汇编去综合的看。
这个逻辑也蛮简单,大体是这样:

​​输入处理​​:从文本框 Text1 获取用户输入(var_44 = Text1.Text)。
​​字符加密​​:遍历输入字符串的每个字符,将其 ASCII 码值增加 10(Asc(var_58) + 10),再转换回字符并拼接为新字符串 var_34。
​​结果验证​​:
若加密后的字符串等于 "kXy^rO|*yXo*m\kMuOn*+",弹出成功消息框("RiCHTiG !")。
否则弹出失败消息框("LEiDER Falsch !")。

写出逆向的脚本:

def decrypt_ciphertext(ciphertext):plaintext = ""for char in ciphertext:decrypted_char = chr(ord(char) - 10)plaintext += decrypted_charreturn plaintexttarget_cipher = "kXy^rO|*yXo*m\kMuOn*+"original_key = decrypt_ciphertext(target_cipher)
print(f"原始key: {original_key}")

在这里插入图片描述
在这里插入图片描述
那么这个cm也就解出来了,逻辑也明白了,接着看下一个cm。

Andrénalin.4

依旧是同一个作者的题目,依旧是32位vb程序。
打开程序后发现样子不太一样:
在这里插入图片描述
右边的状态写的是德语的注册,下面一个小键盘,让输入序列号,发现这个输入框不让输入,只能用程序里面的小键盘来输入。
进到VB Decompiler里面反编译一下看一下:
在这里插入图片描述

下面13个Commandxx_Click()函数,应该对应程序小键盘里面的十三个按键。
四个Timerx_Timer()函数,每个函数里面都是大差不差的加密函数,加密后的数据等于对应的字符串,但是给出了非常多的字符串,哪个是正确的?
去找一下具体的限制条件,发现我们的输入只能是1234567890*#这十二个符号,先看一下每个单独的加密是怎么样:

For var_24 = 1 To Len(var_44) Step 1char = Mid$(var_44, var_24, 1)      ' 取单个字符asc_val = Asc(char)                  ' 获取ASCII值transformed = asc_val + var_CC       ' 关键变换:ASCII值+偏移量hex_str = Hex$(transformed)          ' 转换为十六进制字符串var_34 = var_34 & hex_str            ' 拼接结果
Next

最后的结果一定全是十六进制字符串,所以找一下哪个满足条件。
在xdbg里面搜索字符串,把字符串复制出来,简单处理后找一下。
发现0817E747D7A7D7C7F82836D74747A7F7E7B7C7D826D817E7B7C是完全满足条件的。
根据上面计算的逻辑,写出逆向的Python代码:

def decrypt_key():# 加密字符串(来自代码比较部分)enc_hex = "817E747D7A7D7C7F82836D74747A7F7E7B7C7D826D817E7B7C"# 分割为每2字符一组,共25组(对应25字节)hex_parts = [enc_hex[i:i+2] for i in range(0, len(enc_hex), 2)]# 转换为整数列表(十六进制转十进制)enc_bytes = [int(part, 16) for part in hex_parts]valid_results = []allowed_chars = set("1234567890*#")  # 定义允许的字符集# 遍历所有可能的 var_CC 值(0-255)for cc in range(0, 256):decrypted_chars = []valid = Truefor eb in enc_bytes:# 解密:减去 var_CC 并取模256(处理字节溢出)orig_byte = (eb - cc) % 256char = chr(orig_byte)# 双重验证:可打印ASCII + 指定字符集if not (32 <= orig_byte <= 126 and char in allowed_chars):valid = Falsebreak  # 遇到无效字符,跳过当前ccdecrypted_chars.append(char)if valid:key = ''.join(decrypted_chars)# 验证整个密钥长度(25字符)if len(key) == len(enc_bytes):valid_results.append((cc, key))# 输出结果if valid_results:print("有效的 var_CC 和原始 key:")for cc, key in valid_results:print(f"var_CC = {cc} (0x{cc:02X}), key = '{key}'")print(f"\n共找到 {len(valid_results)} 组有效结果")else:print("未找到有效 key:请检查加密逻辑或字符集约束")# 执行解密
if __name__ == "__main__":decrypt_key()

在这里插入图片描述
这样跑出来了结果74*3032589#**0541238#7412,去测试一下。

在这里插入图片描述

在这里插入图片描述
输入之后发现状态改变了,就是破解成功了,那么这个cm就完成了。

简要总结

一口气做了四个,同一个作者的,全部都是vb语言写的,vb语言没咋学过,所以分析逻辑的时候用了下ai分析,但是整体的破解逻辑还是挺有意思的,四个程序也是由易到难,很好的cm程序了,感谢吾爱的大神们。

相关文章:

  • Generate Permutation
  • ALLEN BRADLEY特价型号1715-OB8DE 模块
  • Make All Equal
  • 灵活运用 NextJS 服务端组件与客户端组件
  • 远程终端登录和桌面访问(嵌入式开发)
  • 网络安全基础--第十天
  • 第十一章 注解
  • 【文献精读】Explaining grokking through circuit efficiency
  • 传输层协议:网络通信的关键纽带
  • Matlab自学笔记五十七:符号运算、可变精度运算、双精度浮点型运算,三种运算精度的概念、比较、选择和应用
  • 主线程极致优化:让CPU“零闲置“的实战方案
  • 制作一款打飞机游戏64:关卡设计
  • 推荐算法八股
  • LVS负载均衡
  • Java复习Day26
  • 线程相关面试题
  • JSCH使用SFTP详细教程
  • 【小红书】API接口,获取笔记列表
  • H.264编码
  • 深拷贝与浅拷贝的区别?如何手写实现一个深拷贝?
  • 公司网站主页图片/合肥瑶海区
  • 织梦网站关闭手机版/免费生成短链接
  • 网站建设 阿里/关键词优化公司排名
  • 河北建造师网/搜索引擎优化的方式
  • 酒生产企业网站建设的目的/新闻稿范文300字
  • 网站设计一般包括什么/百度联盟项目看广告挣钱