欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

xmanctf_2019_crypto_cycle_write_up

程序员文章站 2022-05-14 08:42:26
...
  • 一道xmanctf逆向题目的解答

周末试了试xmanctf的题目,试了一下crypto的cycle那一题,逻辑逆向难度不是很大。主要是对于逆向出来对逻辑,整理成解题思路的过程有点繁琐,需要对程序的精细化处理。分为三个步骤:编码、跳表处理和约束求解,具体分析如下。

  • 编码

对输入字符进行编码,编码算法是:

xmanctf_2019_crypto_cycle_write_up

关键逻辑是有两个:

  1. v2 = byte_202020[i] + v4 –s
  2. s[i] = v2 - 67 *(((0x7A44C6AFC2DD9CA9 * v2) >> 64) >>5 - (v2>>63))

其中v4-s表示当前字符在列表中的index,字符列表是

"0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM{}_!|"

第二步的线性运算将结果填入数组中

 

  • 跳表

跳表就是一个字典,是{key:[content, next_key]}这样一个结构

对每个编码后的字节,通过修改内存0x2024B0进行跳表映射,如当前字节是0x20,则需要在跳表中跳0x20次,跳表的定义在地址0x202080,跳表操作:

off_2024B0 = (void *)*((_QWORD *)off_2024B0 + 1);

xmanctf_2019_crypto_cycle_write_up

  • 约束

最后对跳表后内容进行检查,需要满足两个约束条件:

(1)*(_DWORD *)off_2024B0 != 0xdeadbeef

(2)*(_DWORD *)off_2024B0 < v4

第二个约束条件则限制了每次由编码字节映射到的跳表内容是递增的,检查发现满足上述两个条件的跳表的值只有48个,完整算法如下:

xmanctf_2019_crypto_cycle_write_up

 

最后,根据递增的表值,对输入进行**,可解出flag内容。

附录:write_up.py

import json

source = [
0x24,0x12,0x14,0x25,0x1e,0x19,0x1b,0x17,0x33,0x2e,0x1e,0x35,
0x2f,0xa,0x25,0x0,0x17,0x3d,0x1,0x3d,0x19,0x3b,0x16,0x21,0xf,0x2a,0x12,
0x13,0x26,0x3f,0x37,0x19,0x2a,0x15,0x1f,0x2,0x3a,0xb,0x23,0xb,0xf,0x38,
0x1e,0x4,0x3b,0x16,0x32,0x3d
]

def c2v(c,seed):
	s="0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM{}_!|"
	idx = s.find(c)
	v2 = seed + idx
	value = v2 - 67 *(((0x7A44C6AFC2DD9CA9 * v2) >> 64) >>5 - (v2>>63))
	return value

def get_sequence():
	table = json.load(open('table.json','r'))
	contents = []
	v_kdict = {}
	for key,value in table.items():
		content = int(value[0].strip('L'),16)
		if content !=0xdeadbeef and content != 0x5555557560b0:
			contents.append(content)
			v_kdict[content] = key
	contents.sort()
	return contents,v_kdict

def find_path():
	table = json.load(open('table.json','r'))
	value_list,v_kdict= get_sequence()
	s="0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM{}_!|"
	length = len(s)
	former_key = "0x5555557560b0"
	v = 0xf04cc88a
	flags= ""
	
	for i in range(0,48):
		v = value_list[i]
		seed = source[i]
		key = former_key
		for j in range(0,length):
			key = former_key
			value = c2v(s[j],seed)
			for t in range(0,value):
				content, key = table[key]
			content = content.strip('L')
			if i == 0:
				after_execute_content = value_list[0]
				special_key = v_kdict[after_execute_content]
				if key == special_key:
					flags += s[j]
			if int(content,16) == v:
				former_key = key
				flags += s[j]
				break
		
	print(flags)
		

def main():
	find_path()

if __name__ == '__main__':
	main()