Reverse 练习合集

HUBUCTF 2024

1※ Ez_py

  • 考点:程序分析,base64 换表

  • 题目附件:Ez_py

  • 打开 python 文件,发现程序逻辑是将输入的字符串,经过一个自定义的加密函数加密后,判断是否与最后的字符串相等:

    image

  • 我们根据程序逻辑,先进行 base16 解密,然后进行 base32 解密,依次得到:

    "MZ4DE43XNRKEO42IKQ4GM4DOGJTFM32EN5DHMMDHOA3EI5ZWFNDWOSRSJ53DO42MOA3VIR3XPFZE242JJRCG26JWKZTFOZSINJWUSSA="
    
    "fx2swlTGsHT8fpn2fVoDoFv0gp6Dw6+GgJ2Ov7sLp7TGwyrMsILDmy6VfWfHjmIH"
    
  • 然后将三次的 base64 换的表输出出来看一下:

    "/+9876543210wvutsrqponmlkjihgfedcbaxyzWVUTSRQPONMLKJIHGFEDCBAXYZ"
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/"
    "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
    
  • 接着依次 base64 解密即可得到 flag:

    "flag{Pyth0n_1s_s0_f4ncy!!!}"
    


1※ Maze

  • 考点:程序分析

  • 根据题目提示,是一道迷宫题目,打开 IDA64 分析。发现每一步需要与一个数组内的输入都相同:

    image

  • 那么我们查看这个静态变量得到里面的内容:

    image

  • 将这两串复制下来,根据下方提示 md5 加密后,全转小写,包裹 flag{}:

    path = "sssssrrssrrssllllssssrrnnrrrrssssssllnnllssssrrssllssrrrrnnrrssrrnnnnnnnnllnnrrnnnnllllnnrrnnnnrrssssrrnnnnrrrrnnrrrrssllssllssrrrrssrrssllssssssrrsssssss"
    
    flag{a0ee4ede8b869206add23f51a633f3c2}
    


VMC 2024

2※ rc4_en

  • 考点:RC4

  • 题目附件:rc4_en

  • exeinfope 检查,无壳 32 位程序:

    image

  • IDA32 打开,分析程序逻辑,发现最后比较输入 Buf1 的字符串 RC4 加密后与 Buf2 相等:

    image

  • 在 Init 函数查看初始化 v4 数组的过程:

    image

  • 按照程序流程写出相同的初始化过程:

    S = [0 for x in range(128)]
    G = [0 for x in range(128)]
    for i in range(128):
    	S[i] = i
    	G[i] = key[len_key - 1 - (i % len_key)]
    
    v5 = 0
    for i in range(128):
    	v5 ^= (G[i] + S[i]) %128
    	S[i],S[v5] = S[v5],S[i]
    
    v5 = 0
    for i in range(128):
    	v5 ^= (G[i] + S[i]) %128
    	S[i],S[v5] = S[v5],S[i]
    
  • 查看 RC4 加密逻辑:

    image

  • 照本宣科写出解密脚本,在 python 中注意没有自然溢出,需要 +256 取模:

    v4 = 0;v5 = 0
    for i in range(len_buf):
    	v5 = (v5 + 1) % 128
    	v4 = (v4 + S[v5]) %128
    	S[v5],S[v4] = S[v4],S[v5]
    	buf[i] = (buf[i] - S[ (S[v4]+S[v5])%128 ])%256
    

  • 完整 exp:

    key = [ord(x) for x in "the_key_of_modified_rc4_enc"]
    len_key = len(key)
    print(len_key)
    
    buf = [-59,116,-37,-53,-77,-70,76,-88,-121,101,-92,74,122,-34,111,-61,-49,-90,-83,112,79,-90,-115,-116,114,-109,71,-117,-87,91,102,-74, 88,-116,-80,-74,-64,108,-30,87,-125,91,-41,127,99,61,-108,75,59,-122,121,-125,127,76,116,118,80,-47,74,-104,-120,-101,95,114,-111,115,53,76,-71,-92]
    len_buf = len(buf)
    print(len_buf)
    
    S = [0 for x in range(128)]
    G = [0 for x in range(128)]
    for i in range(128):
    	S[i] = i
    	G[i] = key[len_key - 1 - (i % len_key)]
    
    v5 = 0
    for i in range(128):
    	v5 ^= (G[i] + S[i]) %128
    	S[i],S[v5] = S[v5],S[i]
    
    v4 = 0;v5 = 0
    for i in range(len_buf):
    	v5 = (v5 + 1) % 128
    	v4 = (v4 + S[v5]) %128
    	S[v5],S[v4] = S[v4],S[v5]
    	buf[i] = (buf[i] - S[ (S[v4]+S[v5])%128 ])%256
    
    for x in buf:
    	print(chr(x),end='')
    


3※ 朴实无华的VM

  • 考点:程序分析

  • 题目附件:朴实无华的VM

  • 无壳,IDA 打开发现输入一个长为 24 的字符串,将一个全局数组 dest 与其按位异或,然后将一个全局数组 ptr 传入 vm,作为执行的操作序列:

  • 分析一下 vm 里面的各个操作,将每个函数的功能逆向出来:

  • 写出 vm 各个操作对应的各个操作,需要注意的是 case 10 中赋值给 result 的 v11 是 unsigned int 的类型,而在其他所有 case 中赋值给 result 的都是 unsigned char 的类型:

  • result 的高位始终由 case 10 决定,如果 result 在 case 10 中为负数,那么此时即使到了 case 11 中,result 仍然高位全为 F,会被当做补码存储。那么在 case 11 中的 operator += result 前需要计算一下此时 result 所对应的负数:

  • 所以在 python 脚本中,case 11 需要在操作前判断 result 是否为负数:

    	elif id==11:
    		a = op[idx+1]; idx += 1
    		if res:
    			if res > 0:
    				idx += a-2
    				print(f"add 0x%x"%(a-2))
    			else:
    				idx += -((a-2-1)^0xff)
    				print(f"add 0x%x"%(-((a-2-1)^0xff)))
    
    • 将 dest,ptr 数组扒下来,然后将操作函数写完:
    dest1 = [0x42, 0x3F, 0x53, 0x24, 0x2C, 0x66, 0x5D, 0x5F, 
    		 0x7F, 0x0A, 0x27, 0x39, 0x5F, 0x1D, 0x0B, 0x0F, 
    		 0x2E, 0x0 , 0x6B, 0x2B, 0x5B, 0x19, 0x5C, 0x41]
    print(len(dest1))
    ptr = 0x405000
    
    op=[0x03 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0x00,
    	0x00 ,0x00 ,0x00 ,0x01 ,0x03 ,0x00 ,0x00 ,0x00,
    	0x00 ,0x02 ,0x03 ,0x47 ,0x00 ,0x00 ,0x00 ,0x03,
    	0x03 ,0x25 ,0x5B ,0x00 ,0x00 ,0x04 ,0x03 ,0x91,
    	0xE5 ,0x25 ,0x01 ,0x05 ,0x03 ,0x7F ,0x00 ,0x00,
    	0x00 ,0x06 ,0x03 ,0x18 ,0x00 ,0x00 ,0x00 ,0x07,
    	0x02 ,0x02 ,0x00 ,0x09 ,0x02 ,0x01 ,0x03 ,0x01,
    	0x06 ,0x04 ,0x01 ,0x04 ,0x05 ,0x01 ,0x08 ,0x06,
    	0x01 ,0x01 ,0x01 ,0x03 ,0x0A ,0x00 ,0x01 ,0x0B,
    	0x0A ,0x0A ,0x02 ,0x07 ,0x0B ,0xDE ,0x0C ,0x00,0x00,0x00,0x00,0x00]
    def func(id):
    	global idx,res,flag,arr,op,dest,tag,aim
    	print("id:",id)
    	if id==0:
    		flag = 0
    	elif id==1:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] = arr[a]
    		print(f"arr[%d] = arr[%d]"%(b,a))
    	elif id==2:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] = dest[arr[a]]
    		print(f"arr[%d] = dest[ arr[%d]=%d ] = 0x%x"%(b,a,arr[a],dest[arr[a]]))
    	elif id==3:
    		a = op[idx+1]; b = op[idx+2]; c = op[idx+3]; d = op[idx+4]; e = op[idx+5]; idx += 5
    		arr[e] = a+(b<<8)+(c<<16)+(d<<24)
    		print(f"arr[%d] = 0x%x"%(e,a+(b<<8)+(c<<16)+(d<<24)))
    	elif id==4:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] += arr[a]
    		print(f"arr[%d] += arr[%d]=0x%x  ==> 0x%x"%(b,a,arr[a],arr[b]))
    	elif id==5:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] -= arr[a]
    	elif id==6:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] *= arr[a]
    		print(f"arr[%d] *= arr[%d]=0x%x  ==> 0x%x"%(b,a,arr[a],arr[b]))
    	elif id==7:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] //= arr[a]
    	elif id==8:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] %= arr[a]
    		print(f"arr[%d] m= arr[%d]=0x%x  ==> 0x%x"%(b,a,arr[a],arr[b]))
    	elif id==9:
    		a = op[idx+1]; idx += 1
    		arr[a] += 1
    		print(f"arr[%d] += 1"%(a))
    	elif id==10:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		res = arr[a] - arr[b]
    		aim = arr[b]
    		print(f"res = arr[%d]=0x%x - arr[%d]=0x%x   ==> 0x%x"%(a,arr[a],b,arr[b],res))
    	elif id==11:
    		a = op[idx+1]; idx += 1
    		if res:
    			if res > 0:
    				idx += a-2
    				print(f"add 0x%x"%(a-2))
    			else:
    				idx += -((a-2-1)^0xff)
    				print(f"add 0x%x"%(-((a-2-1)^0xff)))
    	else:
    		tag = 1
    	idx += 1
    
    if __name__ == "__main__":
    	dest = dest1.copy()
    	tag = 1
    	idx = 0
    	flag = 1
    	res = 0
    	aim = 0
    	arr = [0 for i in range(10)]
    	while flag and 0<=idx<=83:
    		func(op[idx])
    		print(hex(idx))
    
  • 运行输出 vm 执行的操作序列发现,只有一个操作将 arr[0] = dest[0],最后将 res = arr[0]-arr[1],然后判断 res 是否为0:

  • 发现此时的 dest[0] 内的原始数据不满足要求,需要输入一个 str[i] = dest[0]^arr[1] 使得 dest[0] 异或后等于 arr[1]:

    inp = dest[0] ^ aim
    print(chr(inp))
    

  • 在 python 脚本中,将 dest[0] 与 v 的 ASCLL 异或,再次执行操作序列发现,程序继续在判断 res=0 后的下一个 case 10;case 11 中,将 operator 减少了 0x24,使得程序循环了:

  • 这一次是 dest[1] 与此时的 arr[1] 相减,然后判断是否为 0,程序结束的时候输出了一个 m 表示此次需要的 str[1]:

  • 那么我们可以猜测,程序会不断循环 len(dest) 次,每次的所需 str[] 的操作数组合起来即为最后的 flag,那么我们改一下 main,套一个 for 循环并收集每一次结束的操作数,写出 python 脚本:

    if __name__ == "__main__":
    	ans = []
    
    	for pos in range(24):
    		dest = dest1.copy()
    		for i in range(len(ans)):
    			dest[i] ^= ans[i]
    
    		tag = 1
    		idx = 0
    		flag = 1
    		res = 0
    		aim = 0
    		arr = [0 for i in range(10)]
    		while flag and 0<=idx<=83:
    			func(op[idx])
    			print(hex(idx))
    
    		inp = dest[pos] ^ aim
    		print(chr(inp))
    		ans.append(inp)
    
    		for x in ans : print(chr(x),end='')
    		print('')
    
  • 最后运行输出 flag:

  • 完整 exp:

    dest1 = [0x42, 0x3F, 0x53, 0x24, 0x2C, 0x66, 0x5D, 0x5F,
    		 0x7F, 0x0A, 0x27, 0x39, 0x5F, 0x1D, 0x0B, 0x0F,
    		 0x2E, 0x0 , 0x6B, 0x2B, 0x5B, 0x19, 0x5C, 0x41]
    print(len(dest1))
    ptr = 0x405000
    
    op=[0x03 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x03 ,0x00,
    	0x00 ,0x00 ,0x00 ,0x01 ,0x03 ,0x00 ,0x00 ,0x00,
    	0x00 ,0x02 ,0x03 ,0x47 ,0x00 ,0x00 ,0x00 ,0x03,
    	0x03 ,0x25 ,0x5B ,0x00 ,0x00 ,0x04 ,0x03 ,0x91,
    	0xE5 ,0x25 ,0x01 ,0x05 ,0x03 ,0x7F ,0x00 ,0x00,
    	0x00 ,0x06 ,0x03 ,0x18 ,0x00 ,0x00 ,0x00 ,0x07,
    	0x02 ,0x02 ,0x00 ,0x09 ,0x02 ,0x01 ,0x03 ,0x01,
    	0x06 ,0x04 ,0x01 ,0x04 ,0x05 ,0x01 ,0x08 ,0x06,
    	0x01 ,0x01 ,0x01 ,0x03 ,0x0A ,0x00 ,0x01 ,0x0B,
    	0x0A ,0x0A ,0x02 ,0x07 ,0x0B ,0xDE ,0x0C ,0x00,0x00,0x00,0x00,0x00]
    print(len(op))
    
    def func(id):
    	global idx,res,flag,arr,op,dest,tag,aim
    	print("id:",id)
    	if id==0:
    		flag = 0
    	elif id==1:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] = arr[a]
    		print(f"arr[%d] = arr[%d]"%(b,a))
    	elif id==2:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] = dest[arr[a]]
    		print(f"arr[%d] = dest[ arr[%d]=%d ] = 0x%x"%(b,a,arr[a],dest[arr[a]]))
    	elif id==3:
    		a = op[idx+1]; b = op[idx+2]; c = op[idx+3]; d = op[idx+4]; e = op[idx+5]; idx += 5
    		arr[e] = a+(b<<8)+(c<<16)+(d<<24)
    		print(f"arr[%d] = 0x%x"%(e,a+(b<<8)+(c<<16)+(d<<24)))
    	elif id==4:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] += arr[a]
    		print(f"arr[%d] += arr[%d]=0x%x  ==> 0x%x"%(b,a,arr[a],arr[b]))
    	elif id==5:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] -= arr[a]
    	elif id==6:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] *= arr[a]
    		print(f"arr[%d] *= arr[%d]=0x%x  ==> 0x%x"%(b,a,arr[a],arr[b]))
    	elif id==7:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] //= arr[a]
    	elif id==8:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		arr[b] %= arr[a]
    		print(f"arr[%d] m= arr[%d]=0x%x  ==> 0x%x"%(b,a,arr[a],arr[b]))
    	elif id==9:
    		a = op[idx+1]; idx += 1
    		arr[a] += 1
    		print(f"arr[%d] += 1"%(a))
    	elif id==10:
    		a = op[idx+1]; b = op[idx+2]; idx += 2
    		res = arr[a] - arr[b]
    		aim = arr[b]
    		print(f"res = arr[%d]=0x%x - arr[%d]=0x%x   ==> 0x%x"%(a,arr[a],b,arr[b],res))
    	elif id==11:
    		a = op[idx+1]; idx += 1
    		if res:
    			if res > 0:
    				idx += a-2
    				print(f"add 0x%x"%(a-2))
    			else:
    				idx += -((a-2-1)^0xff)
    				print(f"add 0x%x"%(-((a-2-1)^0xff)))
    	else:
    		tag = 1
    	idx += 1
    
    if __name__ == "__main__":
    	ans = []
    
    	for pos in range(24):
    		dest = dest1.copy()
    		for i in range(len(ans)):
    			dest[i] ^= ans[i]
    
    		tag = 1
    		idx = 0
    		flag = 1
    		res = 0
    		aim = 0
    		arr = [0 for i in range(10)]
    		while flag and 0<=idx<=83:
    			func(op[idx])
    			print(hex(idx))
    
    		inp = dest[pos] ^ aim
    		print(chr(inp))
    		ans.append(inp)
    
    		for x in ans : print(chr(x),end='')
    		print('')
    	# vvvvvvvvvvvvvvvvvvvvvvvv
    


posted @   浅叶梦缘  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
点击右上角即可分享
微信分享提示
目录导航
目录导航
Reverse 练习合集
HUBUCTF 2024
1※ Ez_py
1※ Maze
VMC 2024
2※ rc4_en
3※ 朴实无华的VM
发布于 2024-11-19 09:18