base64编码
标准形式包含64个ASCⅡ代码A-Z,a-z,0-9,'+'和'/'。(之前文章有记载过)
每三个字符分一组,共3×8=24bit比特,再将这24个比特位每6位分1组,分成4个新的数字作为索引(是索引,不是转为的新字符!),去对应原来数组的字符(6bit位表示2^6=64,正好是原数组0~63索引号数),组成新的编码。
这样以来,base64编码会把3字节的二进制数据编码为4字节的文本数据,长度增加33%。
举例 :上面n1-n4分别为:000000、000010、000100、111111,则索引分别为:0、2、4、63,编码后字符串为ACE/。
解题:
1.检查文件无壳拖入ida,401080和40E0E4是两个关键函数。
第二个方框意思就是比较v5[v3]与byte_40E0E4[v5]相等,则进入下一步if(这里看到别的作者说是比较完所有v5所有的元素)++v3带到最后大于strlen(&v5),执行LABEL_6,再接下来判断一个相等条件,成立得到“yes”语段。若走其他路径则不是error就是no。
2.双击sub_401080,跟进主要查看这两个函数猜测是加密操作和返回值修改。
意思是交换字符,40E0AA和40E0A0的索引为6~14的字符相互交换(双击查看可以猜测这两个就是存储base64编码的函数)。
因为两个地址是连续的,超出40E0A0显示的字符的索引直接衔接到40E0AA上,例如40E0A0[10] = K。这样的话修改后的编码即为:
ABCDEFQRSTUVWXYPGHIJKLMNOZabcdefghijklmnopqrstuvwxyz0123456789+/
跟进401030,do while循环,就是大小写转换。
3.看看返回之前main函数的第三个方框,这样就是说让得出来的结果与40E0E4比较。这一段字符就是ciphertext了。(个人理解)
编写解题脚本:如有错误欢迎随时指正♥♥♥!!
import base64
flag = ""
ciphertext = list("zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9") #转化为列表形式进行遍历
for i in range(len(ciphertext)): # 大小写转换
if 65 <= ord(ciphertext[i]) <= 90:
ciphertext[i] = chr(ord(ciphertext[i]) + 32)
elif 97 <= ord(ciphertext[i]) <= 122:
ciphertext[i] = chr(ord(ciphertext[i]) - 32)
cipher = "".join(ciphertext)
unchanged_base64_text = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
changed_base64_text = 'ABCDEFQRSTUVWXYPGHIJKLMNOZabcdefghijklmnopqrstuvwxyz0123456789+/'
flag = flag.join(base64.b64decode(cipher.translate(str.maketrans(changed_base64_text,unchanged_base64_text)))) # flag{bAse64_h2s_a_Surprise} #解码flag
print(flag)