根据习惯放入IDA:
发现不是c语言之类写的,放入exeinfope看一下
是.net,通过百度发现可以使用dnSpy等反编译软件
使用dnSpy打开:
Module处ctrl + f搜索main:
找到主函数
// Token: 0x06000030 RID: 48 RVA: 0x00002618 File Offset: 0x00001A18
internal unsafe static int main()
{
string b = "3ACF8D62AAA0B630C4AF43AF327CE129D46F0FEB98D9040F713BE65502A5107A";
.std.operator<<u0020>(.__imp_std.cout, (sbyte*)(&.??_C@_0CP@LOCJIKOA@flag?$CIformat?3xxxxxxxxxxxxxxxxxxx@));
IceKey iceKey;
.IceKey.{ctor}(ref iceKey, 0);
try
{
byte[] bytes = Encoding.ASCII.GetBytes(Console.ReadLine());
int num = bytes.Length;
ref byte byte& = ref bytes[0];
byte[] array = new byte[num];
ref byte byte&2 = ref array[0];
MD5CryptoServiceProvider md5CryptoServiceProvider = new MD5CryptoServiceProvider();
byte key;
try
{
MD5CryptoServiceProvider md5CryptoServiceProvider2 = md5CryptoServiceProvider;
key = ref Encoding.ASCII.GetBytes(BitConverter.ToString(md5CryptoServiceProvider.ComputeHash(Encoding.ASCII.GetBytes("iriszero"))).Replace("-", "").ToLower())[0];
}
catch
{
MD5CryptoServiceProvider md5CryptoServiceProvider2;
((IDisposable)md5CryptoServiceProvider2).Dispose();
throw;
}
((IDisposable)md5CryptoServiceProvider).Dispose();
.IceKey.Set(ref iceKey, ref key);
if (0 < num)
{
long num2 = 0L;
uint num3 = (num - 1 >> 3) + 1;
do
{
.IceKey.Encrypt(ref iceKey, ref byte& + num2, ref byte&2 + num2);
num2 += 8L;
num3 += uint.MaxValue;
}
while (num3 > 0U);
}
sbyte* val = ref (BitConverter.ToString(array).Replace("-", "").ToString() == b) ? ref .??_C@_04LOAJBDKD@true@ : ref .??_C@_05LAPONLG@false@;
.std.basic_ostreamu0020>.<<(.std.operator<<u0020>(.__imp_std.cout, val), .__unep@??$endl@DU?$char_traits@D@std@@@std@@$$FYAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@@Z);
if (0 < num)
{
long num4 = 0L;
uint num5 = (num - 1 >> 3) + 1;
do
{
.IceKey.Decrypt(ref iceKey, ref byte&2 + num4, ref byte& + num4);
num4 += 8L;
num5 += uint.MaxValue;
}
while (num5 > 0U);
}
}
catch
{
.___CxxCallUnwindDtor(ldftn(IceKey.{dtor}), (void*)(&iceKey));
throw;
}
.IceKey.{dtor}(ref iceKey);
return 0;
}
细细读一下,虽然没见过.net但大致流程还是看得懂的,还可以使用动态调试来看每一步的作用
输出:
输入:
各变量建立关系,ref应该是地址的意思
将"iriszero",md5加密后值给key
下面明显是一个加密(Encrypt),动态调试加密的数据放在byte&2
加密后的数据和b比较,这里有点不一样,通过动态调试,和b比较的数据是他的16进制而不是字符串
然后,这里本来可以结束程序了,但是后面有一个关键:
它把加密后的数据进行了解密
那我们的思路就比较明确了,有这个解密,我们只需要动态调试的时候把加密后的数据改成b,就会自动解密,然后监视出flag
开始:
比较的时候下一个断点:
启动
确定:
这个一定要输入32位,因为加密,解密和长度有关:
可以直接复制那个格式
bytes(byte&)是输入的数据:
array(byte&2)是加密后的数据
监视这两个值:
复制b的值(不包括引号),找到array的内存,粘贴b的数据:
再次查看监视(注意右键刷新一下):
继续
输出TRUE就是对的:
直接运行完解密部分:
查看bytes:
这就是解密后的数据了,但是如果你直接查看内存,还是:
因为我们没有刷新:
结果:3561636230363233313732346338633336396261653731313136366462653835(直接复制咋是ascii码)
5acb06231724c8c369bae711166dbe85
验证:
七夕快乐



