躺平杯2024 RE WP

1. HIT! 准入认证!

这题有两个flag,分值不同

说走就走的旅行

第一个很简单,就在F12里

太美丽了某校

第二个经过一些加密

第一个加密比较简单,a3的内容也很明确

第二个是魔改base64

换表是下图,注意不要带最后的H,那是下一行第一个字符……

密文在s2

'''
enc1:
p,233,key,p,32
循环32:p[i]=233*p[i]+key[i]
enc2:
p,s1,32
base64换表 asdfghjklqwertyuiopzxcvbnmQWERTYUIOPZXCVBNMASDFGHJKL$%^)!@#&*(-?
s1=s2=%%xv$v^DlcLABQMaxNF^idm*OXrvr$?v-AJoQJczCo$.
'''
import base64
import string
import binascii 
import base64

password = "%%xv$v^DlcLABnMaxNF^ndm*OXr^r$?v-AJoOJczCo$."
standard_base64_table = "asdfghjklqwertyuiopzxcvbnmQWERTYUIOPZXCVBNMASDFGHJKL$%^)!@#&*(-?."
translation_table = str.maketrans(standard_base64_table, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=")
password = [b for b in list(base64.b64decode(password.translate(translation_table)))]
hex_str_list = [hex(num) for num in password]  # 使用列表推导式转换每个元素  
hex_str = ','.join(hex_str_list) 
#print(hex_str)  # 输出

enc = [0xd7,0x55,0x16,0xd1,0x6d,0xad,0x21,0x5c,0xeb,0xa1,
       0x8a,0x80,0x52,0x9b,0xb6,0x60,0x26,0x7c,0x8a,0x53,
       0x36,0x33,0x4f,0xd6,0xfa,0xbc,0x51,0x8b,0x15,0x53,0x99,0x1d]
key = [0x01, 0x09, 0xCD, 0x12, 0x7A, 0x9E, 0x79, 0xF1, 0x74, 0x19, 
       0x19, 0x0C, 0xDB, 0x6F, 0x25, 0x14, 0xDD, 0x61, 0x13, 0xE2, 
       0x8B, 0xBC, 0xC4, 0x26, 0x83, 0xBE, 0xB8, 0x70, 0xAA, 0x4A, 0x90, 0x58]
for i in range(len(enc)):
    for p in range(32,128): 
        if (p * 233 + key[i]) % 256 == enc[i]: #爆破
            print(chr(p), end="")
#flag{7h3_HIT_Lilac_Is_S0_N1c3!!}
2. 躺平聊天室2.0

眼前一糊

眼前一黑

字符串搜索定位主函数

跟进

base64解密

眼前一亮

输入没啥反应

MainActivity中有个对应的方法

看起来是个长度为16的

执行的部分是new t2.b(this, obj, view).start();

点进b,下面有一段加密的部分

用f4475b作为密钥进行了AES-ECB加密,又base64了一下

这里的密钥就是我们输入的内容,根据前面的提示密钥就是第二个flag,长度也符合

3. [投稿]CrackMe

ELF的文件

主函数进去不明所以,动调之后发现跑飞,应该有反调试

查符号表

查看两个函数引用失败,直接在入口处下断点。定位反调试函数返回值的位置,绕过反调试的判断。

动调

这里r12d就是v0要存的值,我们把它改成0

跑到anti_debugger里面,改标志位就可以

继续跑,要输入了

跑到一个解密的地方,进去看看

进去之后断在RSA_private_decrypt下面,点开v4

flag{Xyu_h0is_z7Qs_l0VE}

至此题目是写出来了,但是main函数中的decryption究竟发挥了什么样的作用?为什么两个反调试函数无法查询到交叉引用呢?(感谢朝雾师傅)

我们再审视一下伪代码

CTF中的SMC

SMC一般有俩种破解方法,第一种是找到对代码或数据加密的函数后通过idapython写解密脚本。第二种是动态调试到SMC解密结束的地方dump出来。

SMC的实现是需要对目标内存进行修改的,.text一般是没有写权限的。那么就需要拥有修改目标内存的权限:

在linux系统中,可以通过mprotect函数修改目标内存的权限

在Windows系统中,VirtualProtect函数实现内存权限的修改

因此也可以观察是否有这俩个函数来判断是否进行了SMC。

————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.youkuaiyun.com/Sciurdae/article/details/133717752

从11行的 mprotect 可以判断其实使用了SMC,ENCRYPTED_FUNCTION_ADDR就是加密后代码的地址

18行就是用取反进行代码解密的过程

我们可以动调借助插件dump,也可以用idapython进行静态解码

这里使用的是后者

起始地址是5850

结束在5EF6

addr=0x5B50  
size=0x3A6
for i in range(size):
    tmp=0xff&(~get_wide_byte(addr+i))
    patch_byte(addr+i,tmp)

跑完脚本把下面的数据C起来,在开头P一下

伪代码就很明显了

交叉引用也恢复了正常

其实是一道SMC保护的题目

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值