STEP 00:题目链接
[MRCTF2020]Transform: 传送门
STEP 01:查壳与分析
使用die查壳,无壳,64位程序,可直接ida逆向。
反编译后,可直接看到关键词“code”
按F5对代码仿C代码转换,经过分析,关键点在
追踪dword_40F040和byte_40F0E0过去,并根据代码猜测,这两个位置的数据是两个数组类型的十六进制数,通过dword_40F040的排序对输入的字符串进行重新排序,并经过异或操作后,与目标字符串进行比对得到最终的flag
STEP 02:代码编写
既然看懂代码了,作为一个python选手,开始编码并不断试错吧
#dword_40F040 的十六进制表示
hex_num_1 = ["9", "0A", "0F", "17", "7", "18", "0C", "6", "1", "10", "3", "11", "20", "1D", "0B", "1E", "1B", "16", "4", "0D", "13", "14", "15", "2", "19", "5", "1F", "8", "12", "1A", "1C", "0E", "0"]
#byte_40F0E0 的十六进制表示
hex_num_2 = ["67", "79", "7B", "7F", "75", "2B", "3C", "52", "53", "79", "57", "5E", "5D", "42", "7B", "2D", "2A", "66", "42", "7E", "4C", "57", "79", "41", "6B", "7E", "65", "3C", "5C", "45", "6F", "62", "4D"]
##dword_40F040 转换为十进制
dec_num_1 = list()
for hex_num in hex_num_1:
dec_num_1.append(int(hex_num,16))
print("dec_num_1:",dec_num_1," len:",len(dec_num_1))
#byte_40F0E0 转换为十进制
dec_num_2 = list()
for hex_num in hex_num_2:
dec_num_2.append(int(hex_num,16))
print("dec_num_2:",dec_num_2," len:",len(dec_num_2))
#将数组进行异或操作
temp_strs = list()
for i in range(33):
temp_strs.append(dec_num_1[i] ^ dec_num_2[i])
print(temp_strs,len(temp_strs))
#数组重排并将ASCII码转换为字符
strs = [0] * 33
i = 0
for dec_num in dec_num_1:
strs[dec_num] = temp_strs[i]
i += 1
char_list = list()
for char in strs:
char_list.append(chr(char))
print(''.join(char_list))
运行结果:
dec_num_1: [9, 10, 15, 23, 7, 24, 12, 6, 1, 16, 3, 17, 32, 29, 11, 30, 27, 22, 4, 13, 19, 20, 21, 2, 25, 5, 31, 8, 18, 26, 28, 14, 0] len: 33
dec_num_2: [103, 121, 123, 127, 117, 43, 60, 82, 83, 121, 87, 94, 93, 66, 123, 45, 42, 102, 66, 126, 76, 87, 121, 65, 107, 126, 101, 60, 92, 69, 111, 98, 77] len: 33
[110, 115, 116, 104, 114, 51, 48, 84, 82, 105, 84, 79, 125, 95, 112, 51, 49, 112, 70, 115, 95, 67, 108, 67, 114, 123, 122, 52, 78, 95, 115, 108, 77] len: 33
flag: MRCTF{Tr4nsp0sltiON_Clph3r_1s_3z}
STEP 03:题后总结
十六进制转换为十进制
在python中,如果想要表示十六进制数,需要以字符串的方式进行存储,并使用int(a,16)
的方式进行十进制转换
8 dup(0) 问题
8 dup(0)在汇编中的意思是8个0,所以最后一位是0,而不是“8”,此处问题导致我之前编写的代码第0位一直是0,而第8位被重复替换,导致一直无法输出正确答案
LOBYTE()函数
LOBYTE()得到一个16bit数最低(最右边)那个字节,但是在此题中似乎并未有实际作用,但是既然看到了,就记录下来
数组占位符
在C语言中,我们可以通过int arr[5];
申请数组空间,但是在python中,列表是一个灵活的数据结构,长度不定,里面的元素的类型也可以不完全相同,所以如果要进行列表空间的预申请,可以使用strs = [0] * 33
的方式进行,同理,如果想要用None去填充,则使用strs = [None] * 33
的方式进行。