zoukankan      html  css  js  c++  java
  • [FlareOn6]BMPHIDE

    一个net程序和一张bmp

    用dnspy看看

    private static void Main(string[] args)
    {
        Program.Init();
        Program.yy += 18;
        string filename = args[2];
        string fullPath = Path.GetFullPath(args[0]);
        string fullPath2 = Path.GetFullPath(args[1]);
        byte[] data = File.ReadAllBytes(fullPath2);
        Bitmap bitmap = new Bitmap(fullPath);
        byte[] data2 = Program.h(data);
        Program.i(bitmap, data2);
        bitmap.Save(filename);
    }

    调试发现,Init会触发一个异常

     跟进去发现有个

    进去看看

    public static void CalculateStack()
            {
                Module module = typeof(A).Module;
                ModuleHandle moduleHandle = module.ModuleHandle;
                A.ver4 = (Environment.Version.Major == 4);
                bool flag = A.ver4;
                if (flag)
                {
                    A.ver5 = (Environment.Version.Revision > 17020);
                }
                A.IdentifyLocals();
            }

    进入A.IdentifyLocals()

     进入A.IncrementMaxStack

    看到将程序修改了

    修改的部分为methodBase.MetadataToken == 100663317和methodBase.MetadataToken == 100663316,通过

    可得知一个是h(),另一个是g()

    根据 A.IncrementMaxStack里的方式修改程序

    public static byte g(int idx)//改前
    {
        byte b = (byte)((long)(idx + 1) * (long)((ulong)-306674912));
        byte k = (byte)((idx + 2) * 1669101435);
        return Program.e(b, k);
    }
    public static byte g(int idx)//改后
    {
        byte b = (byte)((long)(idx + 1) * (long)((ulong)309030853));
        byte k = (byte)((idx + 2) * 209897853);
        return Program.e(b, k);
    }
    public static byte[] h(byte[] data)//改前
    {
        byte[] array = new byte[data.Length];
        int num = 0;
        for (int i = 0; i < data.Length; i++)
        {
            int num2 = (int)Program.f(num++);
            int num3 = (int)data[i];
            num3 = (int)Program.e((byte)num3, (byte)num2);
            num3 = (int)Program.a((byte)num3, 7);
            int num4 = (int)Program.f(num++);
            num3 = (int)Program.e((byte)num3, (byte)num4);
            num3 = (int)Program.c((byte)num3, 3);
            array[i] = (byte)num3;
        }
        return array;
    }
    public static byte[] h(byte[] data)//改后
    {
        byte[] array = new byte[data.Length];
        int num = 0;
        for (int i = 0; i < data.Length; i++)
        {
            int num2 = (int)Program.g(num++);
            int num3 = (int)data[i];
            num3 = (int)Program.e((byte)num3, (byte)num2);
            num3 = (int)Program.a((byte)num3, 7);
            int num4 = (int)Program.g(num++);
            num3 = (int)Program.e((byte)num3, (byte)num4);
            num3 = (int)Program.c((byte)num3, 3);
            array[i] = (byte)num3;
        }
        return array;
    }

    修改之后将Init里A.CalculateStack()修改IL指令为nop后保存模块,要在md写入中勾选

    之后就可以调试了,回头看main,重点在

    分析可发现这是一个隐写,隐写的数据在被h处理后经过i写入图片

    public static void i(Bitmap bm, byte[] data)
    {
        int num = Program.j(103);
        for (int i = Program.j(103); i < bm.Width; i++)
        {
            for (int j = Program.j(103); j < bm.Height; j++)
            {
                bool flag = num > data.Length - Program.j(231);
                if (flag)
                {
                    break;
                }
                Color pixel = bm.GetPixel(i, j);
                int red = ((int)pixel.R & Program.j(27)) | ((int)data[num] & Program.j(228));
                int green = ((int)pixel.G & Program.j(27)) | (data[num] >> Program.j(230) & Program.j(228));
                int blue = ((int)pixel.B & Program.j(25)) | (data[num] >> Program.j(100) & Program.j(230));
                Color color = Color.FromArgb(Program.j(103), red, green, blue);
                bm.SetPixel(i, j, color);
                num += Program.j(231);
            }
        }
    }

    这样基本就可以还原了,不过在Init里还有一处坑

    调试可发现,这里将a()转为了b(),c()转为了d(),所以之前看到程序里对a和c的调用其实用的都是b和d

    看一下这几个程序

    public static byte b(byte b, int r)
    {
        for (int i = 0; i < r; i++)
        {
            byte b2 = (b & 128) / 128;
            b = (b * 2 & byte.MaxValue) + b2;
        }
        return b;
    }
    public static byte d(byte b, int r)
    {
        for (int i = 0; i < r; i++)
        {
            byte b2 = (b & 1) * 128;
            b = (b / 2 & byte.MaxValue) + b2;
        }
        return b;
    }
    public static byte g(int idx)
    {
        byte b = (byte)((long)(idx + 1) * (long)((ulong)309030853));
        byte k = (byte)((idx + 2) * 209897853);
        return Program.e(b, k);
    }
    public static byte e(byte b, byte k)
    {
        for (int i = 0; i < 8; i++)
        {
            bool flag = (b >> i & 1) == (k >> i & 1);
            if (flag)
            {
                b = (byte)((int)b & ~(1 << i) & 255);
            }
            else
            {
                b = (byte)((int)b | (1 << i & 255));
            }
        }
        return b;
    }

    b和d是循环移位的操作,e就是个xor,g是个hash,j返回的值是固定的可以直接调出来

    之后可以借助这个程序改为解密算法

    private static void Main(string[] args)
    {
        Program.Init();
        Program.yy += 18;
        Bitmap bitmap = new Bitmap(args[0]);
        byte[] output = new byte[bitmap.Width * bitmap.Height];
        int outidx = 0;
        int hashCtr = 0;
        for (int i = 0; i < bitmap.Width; i++)
        {
            for (int j = 0; j < bitmap.Height; j++)
            {
                Color pixel = bitmap.GetPixel(i, j);
                byte r = pixel.R & 7;
                byte g = pixel.G & 7;
                byte b = (byte)((int)(pixel.B & 3) << 6 | (int)g << 3 | (int)r);
                byte g2 = Program.g(hashCtr++);
                byte g3 = Program.g(hashCtr++);
                byte newByte = Program.a(b, 3);
                newByte ^= g3;
                newByte = Program.c(newByte, 7);
                newByte ^= g2;
                output[outidx++] = newByte;
            }
        }
        File.WriteAllBytes(args[1], output);
    }

    第一次解密后

     再次解密

  • 相关阅读:
    gevent实现基于epoll和协程的服务器
    用greenlet实现协程消费者生产者
    More is better(MST)(求无向图中最大集合元素个数)
    小希的迷宫(MST单棵树判断法则)
    畅通工程再续(MST)
    畅通工程再续
    畅通工程
    还是畅通工程(MST)
    Minimum Inversion Number
    Who Gets the Most Candies?(线段树 + 反素数 )
  • 原文地址:https://www.cnblogs.com/harmonica11/p/13534374.html
Copyright © 2011-2022 走看看