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保护的题目