-
-
[原创]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
赞赏
他的文章
赞赏
雪币:
留言: