首页 > 其他分享 >re | buuctf逆向刷题之crackMe

re | buuctf逆向刷题之crackMe

时间:2023-06-26 16:57:27浏览次数:38  
标签:buuctf sub sm4 re v5 key 刷题 VEH 函数

写在前头

本题来自安洵杯2019 crackMe,涉及到的知识点较多,Mark一下

分析

从main开始

反编译main函数,9行这里触发了一个内存写异常,有点奇怪哈

发现SEH

查看汇编,哦这里注册了一个SEH函数,sub4100F

跟进去看一下,很简单的算法,input划分为4个4字节的值,赋给v5,v5数组按照往后递推的方式,由前4个单元生成后1个单元的值,最后逐个字节取v5[32]到v5[35]的值赋给out

sub_411700长这样,第一个v5单元的值和sub_41170函数异或,函数的参数为v5后三个单元和key的异或,最后计算的值再赋给第5个v5单元

都是异或运算,这个算法要逆过来也很简单,知道最后4个单元的值,往前一个个推就能知道v5[0]到v5[3]的值了,递推规则如下,sub_411760都不用逆,照着IDA抄一下就行

v5[i] = v5[i+4]^sub_411760(v5[i+1]^v5[i+2]^v5[i+3]^(key+4*i))

后面才知道sub_4119f0这个算法叫做sm4,有现成的求逆API可以直接调用

input是用scanf读进来的,如果知道key和out,就可以恢复input

sm4生成box

看一下对key的引用,定位到了Handler_0,一个字符串拷贝到v2,经过运算生成key,和输入没关系是吧,那key可以直接动调获取

其实sub_411172就是用来生成sm4 box的函数,第19行那个异或的数是sm4的一个特征值

发现UEH

继续看一下Handler_0第9行,这里注册了一个UEH函数,点进去分析一下,这里的Str2是固定的一串字符串,顺便还看到了sm4生成的output,output经过sub_41126c计算得到Str1

进入sub_41126c看一下,一眼base64,28行这里=换成!,30行这里对编码表凯撒右移了24位

字符串比较

UEH这个函数返回时eip被修改为sub_411136,点进去看一下,发现是最终的字符串比较,Str2是固定的,Str1由input经过sm4加密和变种base64加密生成

发现VEH

还有一点没搞清,Handler0是如何被调用的,查找交叉引用,定位到sub_412AB0,该函数对base64编码表大小写进行了变换,然后注册了VEH函数来调用Handler

IAT hook

继续向上找引用,这里传入了User32.dll和MessageBoxW,是要搞什么鬼

对里面调用的函数进行符号还原,前面就是找到 user32.dll 对应的 IMAGE_IMPORT_DESCRIPTOR 结构体地址,然后找到 MessageBoxW 对应的 IMAGE_THUNK_DATA 结构体地址,用VirtualProtect修改页属性为可写,用WriteProcessMemory将IMAGE_THUNK_DATA字段覆写为sub_411023函数地址

总结一下,典型的IAT hook,将MessageBoxW的IAT地址替换为了sub_411023的函数地址,该函数完成了VEH的注册

mainCRTStartup对构造函数的初始化

还没完,继续分析这个IAT hook函数是被谁调用的,引用回溯到了rdata这里,往上翻翻

这个地方被tmainCRTStartup调用了

看看tmainCRTStartUp函数,32行这里initterm_e调用了rdata区域里保存的函数,对全局/静态C++类的构造函数进行了初始化

总结

上面的分析是根据结果查找原因,倒着推回去的比较乱,下面再梳理总结下

异常处理的注册

  • 程序初始化时,调用链为start->tmainCRTStartUp->initterm_e->IAT hook,修改MessageBoxW函数的IAT表,在主函数中调用MessageBoxW,实际调用的是注册VEH的函数,并对base64编码表进行了变换
  • 在main函数中对SEH进行了注册
  • 在VEH handler中对UEH进行了注册

异常处理的回调

  • 需要知道一个知识点,Windows 用户态异常发生先找调试器,没有再找 VEH,VEH 处理不了再找 SEH, SEH 还处理不了找 UEF

  • main函数中触发内存写异常,本程序各级异常处理的返回状态都是未完成处理,会继续往下级调异常处理函数,所以本程序的调用顺序为VEH->SEH->UEH

  • VEH中对sm4的box进行了初始化

  • SEH中对input进行sm4加密,获得output

  • UEH中对output进行变种的base64加密,获得Str1,并且和变换过的固定字符串Str2进行比较

总之,题目的算法分析和还原很简单,麻烦的是这些算法没有集中在main中,而是分散到了各个异常处理函数里面,跳来跳去的对分析造成了干扰,不过只要足够有耐心,不断向上查找引用,还是能分析完的

题解

import base64
import sm4

ori = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
now = ''

# sub_412AB0
for c in ori:
	tmp = ord(c)
	if 97 <= tmp <= 122:
		now += chr(tmp - 32)
	elif 65 <= tmp <= 90:
		now += chr(tmp + 32)
	else:
		now += c

ori += '='
now = now[24:] + now[:24] + '!'		# sub_4110FF -> sub_412760
# ori = ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
# now = yzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/abcdefghijklmnopqrstuvwx!

# sub_412C30
str2 = "1UTAOIkpyOSWGv/mOYFY4R!!"
str2_swap = ''
for i in range(0, len(str2), 2):
	str2_swap += str2[i+1] + str2[i]

# sub_41126C -> sub_413090
b64string = ''
for s in str2_swap:
	b64string += ori[now.find(s)]
sm4_encoded = base64.b64decode(b64string)

# sub_412EA0
key = sm4.SM4Key(b"where_are_u_now?")
print key.decrypt(sm4_encoded)

标签:buuctf,sub,sm4,re,v5,key,刷题,VEH,函数
From: https://www.cnblogs.com/z5onk0/p/17506136.html

相关文章

  • mockito5.4.0单元测试(11) --do when家族的方法们:doReturn()|doThrow()| doAnswer()|
    mockito官方文档地址:https://www.javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#do_family_methods_stubs//mock一个对象HashMapmockMap=mock(HashMap.class);  doCallRealMethod方法示例://当mock对象调用put和size方法时,都调用真实的方......
  • Taurus .Net Core 微服务开源框架:Admin 插件【1】 - 微服务节点管理
    前言:最近发现NetCore的文章有点少,特来补几篇。上一篇:Taurus.mvc.NetCore微服务开源框架发布V3.1.7:让分布式应用更高效。自上篇之后,期间更新了4个小版本,更新如下:-----V3.1.7.1----------------1、优化:请求头输出【标识主机IP号、进程号】(2023-06-07)2、优化:Gateway负载......
  • redis常用命令
    Redis常用命令一.redis特点:1.支持数据的持久化,可以将内存的数据保存在磁盘中,重启时再次加载2.存储的数据多样化,支持:string、list、hash、set、zset数据结构的存储3.支持master-slave模式的数据备份二.redis优势:性能高,读的速度为11万次/s,写的速度8.1万次/s三.常用的数据命令string类......
  • redis配置和使用方法
    Redis配置和使用方法一、下载和环境配置1.下载Redis官网:https://github.com/tporadowski/redis/releases,根据本地电脑下载适配的压缩包。2.环境配置下载到本地后,解压到任意目录。进入文件内,复制地址添加到本地电脑的系统环境变量Path路径。二、Redis启动和连接1.启动Redis服务端打......
  • allure邮件报告模板
    Allure邮件报告模板<!DOCTYPEhtml><html><head><metacharset="UTF-8"><title>$PROJECT_NAME-第$BUILD_NUMBER次构建日志</title></head><bodyleftmargin="8"marginwidth="0"topmargin="......
  • Request请求转发
       ......
  • 如何将TLS的安全证书和密钥保存到k8s的secret中?以及在ingress中使用secret中的证书?
    如果要ingress的域名增加TLS的证书,该怎么办? 那如何将证书和密钥保存到k8s的secret中呢? 如果使用自签名的证书,使用下面的命令创建密钥和证书[root@nccztsjb-node-23secrets]#opensslreq-x509\>-newkey\>rsa:4096\>-nodes\>......
  • redhat 下Redis安装
    Redis官网:http://redis.io/ 下载地址:http://redis.io/download安装方法: cdoptwgethttp://download.redis.io/releases/redis-2.8.5.tar.gztar-zxfredis-2.8.5.tar.gzcdredis-2.8.5makesudomakeinstallmake完成后,Src目录下的redis-server和redis-cli两个命名就是red......
  • read: arg count
    在ubuntu环境下使用read出现,read:argcount原因:read没有接收输入的变量解决方法:给read设置一个从标准输入读取输入并赋值给变量。readnumnum是接收变量输入:123456echo$num结果:123456......
  • grep、sed和awk命令的简单使用
                  grep命令选项意义-c匹配行的数量-i忽略大小写-h查询多文件时不显示文件名-l只列出匹配的文件名,不列匹配行-n列出匹配行,并列出行号-s不显示不存在或无匹配的错误信息-v显示不包含匹配文本的所有行-w匹配整词-r递归搜索,搜子目录-E支持扩......