首页
社区
课程
招聘
[原创]KCTF2025 第九题 智斗邪首 writeup
发表于: 2025-9-5 16:55 413

[原创]KCTF2025 第九题 智斗邪首 writeup

2025-9-5 16:55
413

此题一看应该是.net的程序,不过.net的程序本人没怎么玩过,网上下了好些工具都不能反编译,卡了很久,最后还是按网上说法,在 _CorExeMain 下断,查找 OEP 并Dump, 并用de4dot修复,之后扔dnSpy就能反编译了。

namespace _2024003_Crackme
{
	// Token: 0x02000005 RID: 5
	internal class Class1
	{
		// Token: 0x0600000F RID: 15 RVA: 0x00002410 File Offset: 0x00000610
		private static void Main()
		{
			Console.WriteLine("Name:");
			string text = Console.ReadLine();
			Console.WriteLine("SN:");
			string text2 = Console.ReadLine();
			if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2))
			{
				byte[] bytes = Encoding.UTF8.GetBytes(text);
				byte b = 0;
				foreach (byte b2 in bytes)
				{
					b ^= b2;
				}
				int num = (int)(b % 64);
				if (num % 2 == 0)
				{
					num++;
				}
				StringBuilder stringBuilder = new StringBuilder();
				try
				{
					stringBuilder = Class1.KX_RGVjb2Rl(text2);
				}
				catch
				{
					return;
				}
				StringBuilder stringBuilder2 = new StringBuilder(num.ToString());
				if (stringBuilder2 == null || stringBuilder == null || string.IsNullOrWhiteSpace(stringBuilder2.ToString()) || string.IsNullOrWhiteSpace(stringBuilder.ToString()))
				{
					Console.WriteLine("Failed!");
					Console.WriteLine("按任意键结束!");
					Console.ReadKey();
					return;
				}
				if (stringBuilder2.ToString().EndsWith("0") || stringBuilder.ToString().EndsWith("0"))
				{
					Console.WriteLine("Failed!");
					Console.WriteLine("按任意键结束!");
					Console.ReadKey();
					return;
				}
				int num2 = 2040;
				int num3 = 2025;
				Class0 @class = new Class0();
				@class.Precision = 4133025;
				@class.method_0(stringBuilder2, stringBuilder);
				int j = 0;
				try
				{
					while (j < num2)
					{
						if (@class.Quotient.Substring(j * num3, num3) == @class.Quotient.Substring((j + 1) * num3, num3) && @class.Quotient.Substring((j + 1) * num3, num3) == @class.Quotient.Substring((j + 2) * num3, num3))
						{
							j = int.MaxValue;
						}
						if (Class1.KX_VmVyaWZ5U2lnbmFs(@class.Quotient.Substring(j * num3, num3), @class.Quotient.Substring((j + 1) * num3, num3), @class.Quotient.Substring((j + 2) * num3, num3), @class.Quotient.Substring((j + 3) * num3, num3)))
						{
							j++;
						}
						else
						{
							j++;
							IL_0206:
							if (j != num2 - 3)
							{
								Console.WriteLine("Failed!");
								Console.WriteLine("按任意键结束!");
								Console.ReadKey();
								return;
							}
							goto IL_0249;
						}
					}
					goto IL_0206;
				}
				catch
				{
					Console.WriteLine("Failed!");
					Console.WriteLine("按任意键结束!");
					Console.ReadKey();
					return;
				}
				IL_0249:
				Console.WriteLine("Congratulations!");
				Console.WriteLine("按任意键结束!");
				Console.ReadKey();
				return;
			}
		}

		// Token: 0x06000010 RID: 16 RVA: 0x000026EC File Offset: 0x000008EC
		public static bool KX_VmVyaWZ5U2lnbmFs(string string_0, string string_1, string string_2, string string_3)
		{
			Class0 @class = new Class0();
			string text = @class.KX_TXVsdGlTdHJpbmdz(string_0, 5).ToString();
			string text2 = @class.KX_TXVsdGlTdHJpbmdz(string_1, 8).ToString();
			string text3 = @class.KX_TXVsdGlTdHJpbmdz(string_2, 9).ToString();
			string text4 = @class.method_1(text, text2).ToString();
			string text5 = @class.method_1(text4, text3).ToString();
			return string_3 == text5;
		}

		// Token: 0x06000011 RID: 17 RVA: 0x00002750 File Offset: 0x00000950
		public static StringBuilder KX_RGVjb2Rl(string string_0)
		{
			if (string_0.Length < 26 || string_0.Length > 50)
			{
				Environment.Exit(0);
			}
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = new StringBuilder();
			char c = ' ';
			string text = "";
			long num = 0L;
			bool flag = true;
			if (string_0.StartsWith("0"))
			{
				Environment.Exit(0);
			}
			if (string_0.EndsWith("."))
			{
				Environment.Exit(0);
			}
			foreach (char c2 in string_0)
			{
				if (c2 >= '0' && c2 <= '9')
				{
					if (c == ' ')
					{
						c = c2;
						text = "";
					}
					else
					{
						if (text == "" && c2 == '0')
						{
							return stringBuilder2;
						}
						text += c2.ToString();
					}
					flag = false;
				}
				else if (c2 == 'l')
				{
					if (flag)
					{
						return stringBuilder2;
					}
					if (c == ' ')
					{
						return stringBuilder2;
					}
					if (text == "")
					{
						return stringBuilder2;
					}
					if (num != 0L)
					{
						return stringBuilder2;
					}
					num = Convert.ToInt64(text);
					if (num == 0L)
					{
						return stringBuilder2;
					}
					for (;;)
					{
						long num2 = num;
						num = num2 - 1L;
						if (num2 <= 0L)
						{
							break;
						}
						stringBuilder.Append(c);
					}
					num += 1L;
					c = ' ';
					text = "";
					flag = true;
				}
				else
				{
					if (c2 != '.')
					{
						return stringBuilder2;
					}
					if (string.IsNullOrWhiteSpace(stringBuilder.ToString()))
					{
						return stringBuilder2;
					}
					if (!string.IsNullOrEmpty(text))
					{
						return stringBuilder2;
					}
					if (c != ' ' && string.IsNullOrEmpty(text))
					{
						return stringBuilder2;
					}
					c = ' ';
					text = "";
					stringBuilder.Append(c2);
					flag = true;
				}
			}
			if (!flag)
			{
				if (string.IsNullOrWhiteSpace(stringBuilder.ToString()))
				{
					return stringBuilder2;
				}
				if (c == ' ')
				{
					return stringBuilder2;
				}
				if (text == "")
				{
					return stringBuilder2;
				}
				if (num != 0L)
				{
					return stringBuilder2;
				}
				num = Convert.ToInt64(text);
				if (num == 0L)
				{
					return stringBuilder2;
				}
				for (;;)
				{
					long num3 = num;
					num = num3 - 1L;
					if (num3 <= 0L)
					{
						break;
					}
					stringBuilder.Append(c);
				}
			}
			return stringBuilder;
		}
	}
}
namespace _2024003_Crackme
{
	// Token: 0x02000004 RID: 4
	internal class Class0
	{
		// Token: 0x17000001 RID: 1
		// (get) Token: 0x06000003 RID: 3 RVA: 0x00002058 File Offset: 0x00000258
		// (set) Token: 0x06000004 RID: 4 RVA: 0x00002060 File Offset: 0x00000260
		public string Quotient { get; private set; }

		// Token: 0x17000002 RID: 2
		// (get) Token: 0x06000005 RID: 5 RVA: 0x00002069 File Offset: 0x00000269
		// (set) Token: 0x06000006 RID: 6 RVA: 0x00002071 File Offset: 0x00000271
		public string Remainder { get; private set; }

		// Token: 0x17000003 RID: 3
		// (get) Token: 0x06000007 RID: 7 RVA: 0x0000207A File Offset: 0x0000027A
		// (set) Token: 0x06000008 RID: 8 RVA: 0x00002082 File Offset: 0x00000282
		public int Precision { get; set; }

		// Token: 0x06000009 RID: 9 RVA: 0x00002108 File Offset: 0x00000308
		public void method_0(StringBuilder stringBuilder_0, StringBuilder stringBuilder_1)
		{
			string text = "";
			try
			{
				string text2 = Class0.KX_RXh0cmFjdFJlc291cmNlVG9UZW1w();
				using (Process process = Process.Start(new ProcessStartInfo
				{
					FileName = text2,
					Arguments = string.Concat(new string[]
					{
						stringBuilder_0.ToString(),
						" ",
						stringBuilder_1.ToString(),
						" ",
						this.Precision.ToString()
					}),
					UseShellExecute = false,
					RedirectStandardOutput = true,
					CreateNoWindow = true
				}))
				{
					text = process.StandardOutput.ReadToEnd();
					process.WaitForExit();
				}
				File.Delete(text2);
			}
			catch (Exception ex)
			{
				Environment.Exit(0);
				Console.WriteLine("错误: " + ex.Message);
			}
			if (text == "")
			{
				return;
			}
			if (text.Contains("E"))
			{
				string[] array = text.Split(new char[] { '.', 'E', '-' });
				this.Quotient = "1" + array[1];
				if (text.Contains('-'))
				{
					this.Quotient = this.Quotient.PadLeft(this.Quotient.Length + Convert.ToInt32(array[array.Length - 1]) - 1, '0');
				}
			}
		}

		// Token: 0x0600000A RID: 10 RVA: 0x00002278 File Offset: 0x00000478
		private static string KX_RXh0cmFjdFJlc291cmNlVG9UZW1w()
		{
			Assembly.GetExecutingAssembly();
			string text = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".exe");
			using (FileStream fileStream = new FileStream(text, FileMode.Create, FileAccess.Write))
			{
				fileStream.Write(KX_UmVzb3VyY2Ux._20250805Calc, 0, KX_UmVzb3VyY2Ux._20250805Calc.Length);
				fileStream.Flush();
			}
			return text;
		}

		// Token: 0x0600000B RID: 11 RVA: 0x0000208B File Offset: 0x0000028B
		private static int smethod_0(string string_2, string string_3)
		{
			if (string_2.Length != string_3.Length)
			{
				return string_2.Length - string_3.Length;
			}
			return string.Compare(string_2, string_3, StringComparison.Ordinal);
		}

		// Token: 0x0600000C RID: 12 RVA: 0x000022F4 File Offset: 0x000004F4
		public StringBuilder method_1(string string_2, string string_3)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			if (Class0.smethod_0(string_2, string_3) < 0)
			{
				string text = string_2;
				string_2 = string_3;
				string_3 = text;
			}
			for (int i = 0; i < string_2.Length; i++)
			{
				int num2 = (int)(string_2[string_2.Length - 1 - i] - '0');
				int num3 = (int)((i < string_3.Length) ? (string_3[string_3.Length - 1 - i] - '0') : '\0');
				int num4 = num2 + num3 + num;
				num = 0;
				if (num4 >= 10)
				{
					num = num4 / 10;
					num4 %= 10;
				}
				stringBuilder.Insert(0, num4.ToString());
			}
			if (num > 0)
			{
				stringBuilder.Insert(0, num.ToString());
			}
			return stringBuilder;
		}

		// Token: 0x0600000D RID: 13 RVA: 0x0000239C File Offset: 0x0000059C
		public StringBuilder KX_TXVsdGlTdHJpbmdz(string string_2, int int_1)
		{
			StringBuilder stringBuilder = new StringBuilder();
			int num = 0;
			for (int i = 0; i < string_2.Length; i++)
			{
				int num2 = (int)(string_2[string_2.Length - 1 - i] - '0') * int_1 + num;
				num = 0;
				if (num2 >= 10)
				{
					num = num2 / 10;
					num2 %= 10;
				}
				stringBuilder.Insert(0, num2.ToString());
			}
			if (num > 0)
			{
				stringBuilder.Insert(0, num.ToString());
			}
			return stringBuilder;
		}

		// Token: 0x04000001 RID: 1
		[CompilerGenerated]
		private string string_0;

		// Token: 0x04000002 RID: 2
		[CompilerGenerated]
		private string string_1;

		// Token: 0x04000003 RID: 3
		[CompilerGenerated]
		private int int_0;
	}
}

程序运行时会解出一个exe,文件到临时文件,再传入参数调用它,并读取它的输出,而exe文件是PyInstaller打包的PYTHON脚本,用pyinstxtractor解包,并反编译20250805Calc-pub.pyc:

from decimal import Decimal, getcontext
import os
import sys

def reciprocal(m, n, prec):
    getcontext().prec = int(prec)
    result = Decimal(m) / Decimal(n)
    return result

def main(arg1, arg2, arg3):
    sys.set_int_max_str_digits(int(arg3))
    reciprocal_value = reciprocal(arg1, arg2, arg3)
    print(reciprocal_value)

if __name__ == '__main__':
    arg1 = sys.argv[1]
    arg2 = sys.argv[2]
    arg3 = sys.argv[3]
    main(arg1, arg2, arg3)

把以上反编译的JAVA和python代码扔AI,它直接给了我一个get_sn:

import sys
from itertools import groupby

def get_m(name):
    bytes_ = name.encode('utf-8')
    b = 0
    for byte in bytes_:
        b ^= byte
    num = b % 64
    if num % 2 == 0:
        num += 1
    return num

def encode(str_N):
    runs = [(key, len(list(group))) for key, group in groupby(str_N)]
    result = []
    for i, (d, count) in enumerate(runs):
        if i == len(runs) - 1:
            result.append(d + str(count))
        else:
            result.append(d + str(count) + 'l')
    return ''.join(result)

def get_sn(name):
    sys.set_int_max_str_digits(0)
    s = "54" + "9"*2022 + "504" + "9"*2022 + "55" + "9"*2023 + "725"
    n_example = int(s)
    k = n_example // 55
    m = get_m(name)
    N = k * m
    str_N = str(N)
    sn = encode(str_N)
    return sn

name = 'KCTF'
print(f"name:{name}, sn:{get_sn(name)}")

得到:

name:KCTF, sn:21l61l92022l71l51l61l92022l71l81l31l92022l81l61l51



传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回