xmanctf_2019_crypto_cycle_write_up

  • 一道xmanctf逆向题目的解答

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

  • 编码

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

关键逻辑是有两个:

  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);

  • 约束

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

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

(2)*(_DWORD *)off_2024B0 < v4

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

 

最后,根据递增的表值,对输入进行爆破,可解出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()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值