吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3205|回复: 9
收起左侧

[CrackMe] .net混淆CrackMe4

[复制链接]
hackjam 发表于 2019-1-19 22:53
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。

本帖最后由 hackjam 于 2019-1-21 01:16 编辑

.net混淆CrackMe4
之前的:
.net混淆CrackMe1 -> https://www.52pojie.cn/thread-853485-1-1.html
.net混淆CrackMe2 -> https://www.52pojie.cn/thread-853763-1-1.html
.net混淆CrackMe3 -> https://www.52pojie.cn/thread-854229-1-1.html

破解前:


破解后:



度盘:
链接: https://pan.baidu.com/s/1G3mBHmdbEsXKdSpzwn8obQ
提取码: 6575

吾爱盘:



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 1吾爱币 +6 热心值 +1 收起 理由
CrazyNut + 6 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

wwh1004 发表于 2019-1-20 10:28
不知道是国外哪个壳,用自己之前写的控制流分析库把控制流混淆清掉了(不是de4dot.blocks!!!!!!!是自己写的,最后附上的代码是清理控制流混淆的,可能你不能直接套给de4dot用)

脱完了才发现原来里面还有代码虚拟化,虚拟化前的代码还有许多是无效代码,用来防止分析的

懒得弄了,.NET的CrackMe都快变成了UnpackMe。
这种CM其实真没太大意思的,全是靠壳的强度。
这个虚拟化也不是特别难,2个数组,一个数组储存局部变量,一个数组负责对访问局部变量数组的下标,也就是index,进行解密操作。
虚拟化只是虚拟化了控制流,没把指令也虚拟化掉,说白了就是加强版控制流混淆。可还原性上来说比Agile.NET的虚拟化好还原的多,这个只需要干掉控制流混淆,恢复下局部变量的访问就清掉虚拟化了。而Agile.NET的代码虚拟化是真的把所有指令都虚拟化了,还原起来很麻烦,虽然反编译正常,但是不一定能正常运行,如果研究过Agile.NET虚拟机的应该都清楚,就不多说了。
有时间我再看看把这个虚拟化的还原写出来。
[C#] 纯文本查看 复制代码
class Program {
	static void Main(string[] args) {
		new Thread(Execute, 4096 * 1000).Start();
	}

	private static void Execute() {
		using (ModuleDefMD moduleDef = ModuleDefMD.Load(@"I:\Downloads\CrackMe-J4\CrackMe-J4-cleaned.exe")) {
			foreach (MethodDef methodDef in moduleDef.EnumerateAllMethodDefs())
				if (methodDef.HasBody && !methodDef.Body.HasExceptionHandlers) {
					BlockParser parser;
					MethodBlock methodBlock;
					BlockDeparser deparser;

					methodDef.SimplifyMacros();
					if (!IsObfuscated(methodDef.Body.Instructions))
						continue;
					parser = new BlockParser(methodDef.Body.Instructions, methodDef.Body.ExceptionHandlers, methodDef.Body.Variables);
					parser.Parse(true);
					methodBlock = parser.MethodBlock;
					Decflow(methodBlock);
					BlockSorter.Sort(methodBlock);
					deparser = new BlockDeparser(methodBlock);
					deparser.Deparse();
					methodDef.Body.Instructions.Clear();
					foreach (Instruction instruction in deparser.Instructions)
						methodDef.Body.Instructions.Add(instruction);
					methodDef.Body.Variables.Clear();
					foreach (Local variable in deparser.Variables)
						methodDef.Body.Variables.Add(variable);
				}
			moduleDef.Write(@"I:\Downloads\CrackMe-J4\CrackMe-J4-cf.exe");
		}
	}

	private static bool IsObfuscated(IList<Instruction> instructions) {
		if (instructions.Count < 3)
			return false;
		if (instructions[0].OpCode.Code != Code.Ldc_I4 ||
			instructions[1].OpCode.Code != Code.Stloc ||
			instructions[2].OpCode.Code != Code.Br)
			return false;
		return true;
	}

	private static void Decflow(MethodBlock methodBlock) {
		Local ipVariable;
		int maxCaseIp;
		BasicBlock[] jumpTable;

		ipVariable = (Local)ToBasicBlock(methodBlock.FirstBlock).Instructions[1].Operand;
		foreach (IBlock block in methodBlock.Blocks) {
			bool isCase;
			int targetIp;
			BasicBlock body;

			isCase = IsCase(ToBasicBlock(block), ipVariable, out targetIp, out body);
			block.PushExtraData(new BlockInfo() {
				IsCase = isCase,
				TargetIp = targetIp,
				Body = body
			});
		}
		// set extra-data
		maxCaseIp = methodBlock.Blocks.Max(block => ToBasicBlock(block).PeekExtraData<BlockInfo>().TargetIp);
		jumpTable = new BasicBlock[maxCaseIp + 1];
		foreach (IBlock block in methodBlock.Blocks) {
			BasicBlock basicBlock;
			BlockInfo blockInfo;

			basicBlock = ToBasicBlock(block);
			blockInfo = basicBlock.PeekExtraData<BlockInfo>();
			if (blockInfo.IsCase)
				jumpTable[blockInfo.TargetIp] = blockInfo.Body;
		}
		// build jump-table
		foreach (IBlock block in methodBlock.Blocks) {
			BasicBlock basicBlock;
			BlockInfo blockInfo;
			int targetIp;
			List<Instruction> instructions;
			int maxIndex;

			basicBlock = ToBasicBlock(block);
			blockInfo = basicBlock.PeekExtraData<BlockInfo>();
			if (blockInfo.IsCase)
				continue;
			if (!HasIpSetter(basicBlock, ipVariable, out targetIp))
				continue;
			instructions = basicBlock.Instructions;
			maxIndex = instructions.Count - 1;
			SetNop(instructions[maxIndex - 2]);
			SetNop(instructions[maxIndex - 1]);
			basicBlock.LastInstruction.Operand = jumpTable[targetIp].FirstInstruction;
			basicBlock.FallThrough = jumpTable[targetIp];
		}
		// fix jump
		foreach (IBlock block in methodBlock.Blocks)
			block.PopExtraData();
		// clean extra-data
	}

	private static void SetNop(Instruction instruction) {
		instruction.OpCode = OpCodes.Nop;
		instruction.Operand = null;
	}

	private static bool IsCase(BasicBlock basicBlock, Local ipVariable, out int targetIp, out BasicBlock body) {
		List<Instruction> instructions;

		targetIp = 0;
		body = null;
		instructions = basicBlock.Instructions;
		if (instructions.Count < 4)
			return false;
		if (instructions[0].OpCode.Code != Code.Ldloc || instructions[0].Operand != ipVariable ||
			instructions[1].OpCode.Code != Code.Ldc_I4 ||
			instructions[2].OpCode.Code != Code.Ceq ||
			(instructions[3].OpCode.Code != Code.Brfalse && instructions[3].OpCode.Code != Code.Brtrue))
			return false;
		targetIp = (int)instructions[1].Operand;
		if (instructions[3].OpCode.Code == Code.Brfalse)
			body = basicBlock.FallThrough;
		else
			body = basicBlock.ConditionalTarget;
		return true;
	}

	private static bool HasIpSetter(BasicBlock basicBlock, Local ipVariable, out int targetIp) {
		List<Instruction> instructions;
		int maxIndex;

		targetIp = 0;
		instructions = basicBlock.Instructions;
		if (instructions.Count < 3)
			return false;
		maxIndex = instructions.Count - 1;
		if (instructions[maxIndex - 2].OpCode.Code != Code.Ldc_I4 ||
			instructions[maxIndex - 1].OpCode.Code != Code.Stloc || instructions[maxIndex - 1].Operand != ipVariable ||
			instructions[maxIndex].OpCode.Code != Code.Br)
			return false;
		targetIp = (int)instructions[maxIndex - 2].Operand;
		return true;
	}

	private static BasicBlock ToBasicBlock(IBlock block) {
		return (BasicBlock)block;
	}

	private sealed class BlockInfo {
		private bool _isCase;
		private int _targetIp;
		private BasicBlock _body;

		public bool IsCase {
			get => _isCase;
			set => _isCase = value;
		}

		public int TargetIp {
			get => _targetIp;
			set => _targetIp = value;
		}

		public BasicBlock Body {
			get => _body;
			set => _body = value;
		}
	}
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 3吾爱币 +5 热心值 +3 收起 理由
CrazyNut + 3 + 1 膜拜大佬
雾落尘 + 1 + 1 太可怕了....
hackjam + 1 + 1 我很赞同!

查看全部评分

wgh1256 发表于 2019-1-19 23:10
 楼主| hackjam 发表于 2019-1-20 10:38
wwh1004 发表于 2019-1-20 10:28
不知道是国外哪个壳,用自己之前写的控制流分析库把控制流混淆清掉了(不是de4dot.blocks!!!!!!!是自己写的 ...

不错,大神有心了
javazhangwei 发表于 2019-1-21 12:15
这是干嘛的嗯嗯嗯嗯
wgh1256 发表于 2019-1-21 13:30
javazhangwei 发表于 2019-1-21 12:15
这是干嘛的嗯嗯嗯嗯

这是尝试破解的样本,用来检验破解人员的技术实力。
 楼主| hackjam 发表于 2019-1-25 11:26
没人了吗,欢迎攻克
梦游枪手 发表于 2019-1-25 12:24
确实没办法,混淆的太过了,楼上的大佬贴出的代码我没有VS编译不了。用x64dbg调试,一停在断点程序就瘫了。dnSpy切换成IL指令集并且关掉局部变量可以调试,但是看不到变量值也没办法继续调下去了

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
hackjam + 1 + 1 热心回复!

查看全部评分

tfrist 发表于 2019-1-30 02:47
我自己试了一下 其中有几个类把dnspy搞死了  卡死在decompiling了 请这种情况下怎么搞? 我只用了de4dot去去掉混淆的名字 别的不知道怎么继续。
梦游枪手 发表于 2019-2-4 14:10
用了些笨方法,破解了不到一半吧,另外一部分可能需要一组key才能解了

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册[Register]

x

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
hackjam + 1 + 1 热心回复!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-28 08:53

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表