• XSS.stack #1 – первый литературный журнал от юзеров форума

DefenderCheck async (ловим сигнатуры WD асинхронно)

salsa20

(L2) cache
Пользователь
Регистрация
03.05.2019
Сообщения
498
Реакции
110
Гарант сделки
1
Я хотел бы поделиться с вами интересным проектом, который мог бы быть полезным для анализа сигнатур от WD. Возможно, вы уже знакомы с ним - https://github.com/matterpreter/DefenderCheck.

После некоторого времени проведенного за изучением и разработкой, я создал асинхронную версию этого проекта, и я должен признать, что она работает гораздо быстрее. Теперь можно быстро обрабатывать большие объемы данных и искать сигнатуры, которые могут указывать на проблемы с WD. Просто скопируйте сигнатуру в hex-редакторе, используя код из проекта, и вы сможете найти и исправить проблему.

0A1Ql9b.gif


Для компиляции замените код на следующий:

C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DefenderCheck
{
    static class ProcessExtensions
    {
        public static Task WaitForExitAsync(this Process process, CancellationToken cancellationToken = default)
        {
            if (process == null)
                throw new ArgumentNullException(nameof(process));

            var tcs = new TaskCompletionSource<bool>();

            process.EnableRaisingEvents = true;
            process.Exited += (s, e) => tcs.TrySetResult(true);
            if (cancellationToken != default)
                cancellationToken.Register(() => tcs.TrySetCanceled());

            return tcs.Task;
        }
    }

    class Program
    {
        private const string TempDirectoryPath = @"C:\Temp";
        private const string TestFilePath = @"C:\Temp\testfile.exe";

        static async Task Main(string[] args)
        {
            bool debug = false;
            if (args.Length == 2 && args[1].Contains("debug"))
            {
                debug = true;
            }

            string targetFile = args[0];
            if (!File.Exists(targetFile))
            {
                Console.WriteLine("[-] Can't access the target file");
                return;
            }

            string originalFileDetectionStatus = Scan(targetFile).ToString();
            if (originalFileDetectionStatus.Equals("NoThreatFound"))
            {
                if (debug) { Console.WriteLine("Scanning the whole file first"); }
                Console.WriteLine("[+] No threat found in the submitted file!");
                return;
            }

            if (!Directory.Exists(TempDirectoryPath))
            {
                Console.WriteLine(@"[-] C:\Temp doesn't exist. Creating it...");
                Directory.CreateDirectory(TempDirectoryPath);
            }

            byte[] originalFileContents = await ReadAllBytesAsync(targetFile);
            int originalFileSize = originalFileContents.Length;
            Console.WriteLine("Target file size: {0} bytes", originalFileContents.Length);
            Console.WriteLine("Analyzing...\n");

            byte[] buffer = new byte[originalFileSize / 2];
            Array.Copy(originalFileContents, 0, buffer, 0, buffer.Length);
            int lastGood = 0;

            bool threatFound = false;

            while (!threatFound)
            {
                if (debug) { Console.WriteLine("Testing {0} bytes", buffer.Length); }
                await WriteAllBytesAsync(TestFilePath, buffer);

                List<Task<ScanResult>> scanTasks = new List<Task<ScanResult>>
                {
                    Task.Run(() => Scan(TestFilePath))
                };
                for (int i = 0; i < lastGood; i += buffer.Length)
                {
                    int remainingBytes = originalFileContents.Length - i;
                    int bytesToCopy = Math.Min(buffer.Length, remainingBytes);
                    byte[] previousPart = new byte[bytesToCopy];
                    Array.Copy(originalFileContents, i, previousPart, 0, bytesToCopy);
                    string previousFilePath = $@"{TempDirectoryPath}\previousPart{i}.exe";
                    await WriteAllBytesAsync(previousFilePath, previousPart);
                    scanTasks.Add(Task.Run(() => Scan(previousFilePath)));
                }

                await Task.WhenAll(scanTasks);

                foreach (var task in scanTasks)
                {
                    string detectionStatus = task.Result.ToString();
                    if (detectionStatus.Equals("ThreatFound"))
                    {
                        if (debug) { Console.WriteLine("Threat found. Half-splitting again..."); }
                        byte[] tempArray = await HalfSplitterAsync(buffer, lastGood);
                        Array.Resize(ref buffer, tempArray.Length);
                        Array.Copy(tempArray, buffer, tempArray.Length);
                        break;
                    }
                    else if (detectionStatus.Equals("NoThreatFound"))
                    {
                        if (debug) { Console.WriteLine("No threat found. Going up 50% of the current size."); };
                        lastGood = buffer.Length;
                        byte[] tempArray = Overshot(originalFileContents, buffer.Length);
                        if (tempArray.Length == buffer.Length)
                        {
                            Console.WriteLine("Exhausted the search. The binary looks good to go!");
                            Environment.Exit(0);
                        }
                        Array.Resize(ref buffer, tempArray.Length);
                        Array.Copy(tempArray, buffer, tempArray.Length);
                    }
                    else
                    {
                        Console.WriteLine("Unknown detection status: {0}", detectionStatus);
                        Environment.Exit(1);
                    }
                }
            }
        }
        public static async Task<ScanResult> ScanByteArray(byte[] bytes)
        {
            // Создаем временный файл для сохранения массива байтов
            string tempFilePath = Path.Combine(TempDirectoryPath, "tempfile.exe");

            try
            {
                // Записываем массив байтов во временный файл
                await WriteAllBytesAsync(tempFilePath, bytes);

                // Выполняем сканирование временного файла
                ScanResult scanResult = await Scan(tempFilePath);

                return scanResult;
            }
            finally
            {
                // Удаляем временный файл
                if (File.Exists(tempFilePath))
                {
                    File.Delete(tempFilePath);
                }
            }
        }

        public static async Task<byte[]> HalfSplitterAsync(byte[] originalarray, int lastgood)
        {
            int startIndex = lastgood;
            int endIndex = originalarray.Length;
            int bufferSize = endIndex - startIndex;

            if (bufferSize <= 0)
            {
                Console.WriteLine("[-] Invalid buffer size. Something is wrong...");
                Environment.Exit(1);
            }

            byte[] splitarray = new byte[bufferSize];
            Array.Copy(originalarray, startIndex, splitarray, 0, bufferSize);

            // Scan the split array for threats
            ScanResult scanResult = await ScanByteArray(splitarray);
            if (scanResult == ScanResult.ThreatFound)
            {
                Console.WriteLine("[!] Identified end of bad bytes at offset 0x{0:X} in the original file", endIndex);
                await Scan(TestFilePath, true);

                byte[] offendingBytes = new byte[256];
                int offendingBytesLength = Math.Min(bufferSize, 256);
                Array.Copy(splitarray, bufferSize - offendingBytesLength, offendingBytes, 0, offendingBytesLength);

                HexDump(offendingBytes, 16);
                File.Delete(TestFilePath);
                Environment.Exit(0);
            }

            return splitarray;
        }



        public static byte[] Overshot(byte[] originalArray, int splitArraySize)
        {
            int newSize = splitArraySize + (originalArray.Length - splitArraySize) / 2;
            if (newSize == originalArray.Length - 1)
            {
                Console.WriteLine("Exhausted the search. The binary looks good to go!");
                Environment.Exit(0);
            }

            byte[] newArray = new byte[newSize];
            Array.Copy(originalArray, 0, newArray, 0, newArray.Length);
            return newArray;
        }

        public static async Task<byte[]> ReadAllBytesAsync(string path)
        {
            using (FileStream sourceStream = new FileStream(path,
                FileMode.Open, FileAccess.Read, FileShare.Read,
                bufferSize: 4096, useAsync: true))
            {
                int bufferSize = (int)sourceStream.Length;
                byte[] buffer = new byte[bufferSize];
                await sourceStream.ReadAsync(buffer, 0, bufferSize);
                return buffer;
            }
        }

        public static async Task WriteAllBytesAsync(string path, byte[] bytes)
        {
            using (FileStream destinationStream = new FileStream(path,
                FileMode.Create, FileAccess.Write, FileShare.None,
                bufferSize: 4096, useAsync: true))
            {
                await destinationStream.WriteAsync(bytes, 0, bytes.Length);
            }
        }

        public static async Task<ScanResult> Scan(string file, bool getSig = false)
        {
            if (!File.Exists(file))
            {
                return ScanResult.FileNotFound;
            }

            var process = new Process();
            var mpcmdrun = new ProcessStartInfo(@"C:\Program Files\Windows Defender\MpCmdRun.exe")
            {
                Arguments = $"-Scan -ScanType 3 -File \"{file}\" -DisableRemediation -Trace -Level 0x10",
                CreateNoWindow = true,
                ErrorDialog = false,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                WindowStyle = ProcessWindowStyle.Hidden
            };

            process.StartInfo = mpcmdrun;
            process.Start();
            await process.WaitForExitAsync(); // Ожидание асинхронного завершения процесса

            if (!process.HasExited)
            {
                process.Kill();
                return ScanResult.Timeout;
            }

            if (getSig)
            {
                string stdout;
                while ((stdout = await process.StandardOutput.ReadLineAsync()) != null)
                {
                    if (stdout.Contains("Threat  "))
                    {
                        string[] sig = stdout.Split(' ');
                        string sigName = sig[19];
                        Console.WriteLine($"File matched signature: \"{sigName}\"\n");
                        break;
                    }
                }
            }

            switch (process.ExitCode)
            {
                case 0:
                    return ScanResult.NoThreatFound;
                case 2:
                    return ScanResult.ThreatFound;
                default:
                    return ScanResult.Error;
            }
        }

        public enum ScanResult
        {
            [Description("No threat found")]
            NoThreatFound,
            [Description("Threat found")]
            ThreatFound,
            [Description("The file could not be found")]
            FileNotFound,
            [Description("Timeout")]
            Timeout,
            [Description("Error")]
            Error
        }

        //Adapted from https://www.codeproject.com/Articles/36747/Quick-and-Dirty-HexDump-of-a-Byte-Array
        public static void HexDump(byte[] bytes, int bytesPerLine = 16)
        {
            if (bytes == null)
            {
                Console.WriteLine("[-] Empty array supplied. Something is wrong...");
                return;
            }

            int bytesLength = bytes.Length;
            int totalLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
            StringBuilder result = new StringBuilder();

            for (int line = 0; line < totalLines; line++)
            {
                int lineStart = line * bytesPerLine;
                int lineEnd = Math.Min(lineStart + bytesPerLine, bytesLength);
                int lineLength = lineEnd - lineStart;

                // Hex representation
                StringBuilder hexBuilder = new StringBuilder(lineLength * 3);
                for (int i = lineStart; i < lineEnd; i++)
                {
                    hexBuilder.Append(bytes[i].ToString("X2"));
                    hexBuilder.Append(" ");
                }
                string hexLine = hexBuilder.ToString().PadRight(bytesPerLine * 3);

                // ASCII representation
                StringBuilder asciiBuilder = new StringBuilder(lineLength);
                for (int i = lineStart; i < lineEnd; i++)
                {
                    byte b = bytes[i];
                    char c = (b >= 32 && b <= 126) ? (char)b : '.';
                    asciiBuilder.Append(c);
                }
                string asciiLine = asciiBuilder.ToString();

                // Combine hex and ASCII lines
                string fullLine = $"{hexLine}  {asciiLine}\n";
                result.Append(fullLine);
            }

            Console.WriteLine(result.ToString());
        }

    }
}


Надеюсь, что этот проект будет полезным для вас, и я призываю вас воспользоваться им. Если у вас есть какие-либо вопросы или отзывы, буду рад услышать их.

Удачи и продуктивного анализа сигнатур!
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Thanks for sharing this is usful with signature but when it comes to new Windows defender and new generation of all Antivurs vendros Signature is not a problem because you can bypass it easly the problem is Behavior sheild most of the time
 
Было время переписал на С++ код, также добавил вывод инструкции через capstone чтобы сразу понимать в чем трабла.

1712366534249.png


x64

1712368823325.png


C++:
#include <windows.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
#include <capstone/capstone.h>
#include <algorithm>
#include <iostream>

enum class ScanResult
{
    NoThreatFound,
    ThreatFound,
    FileNotFound,
    Timeout,
    Error
};

template <typename T>
T my_own_min(T a, T b)
{
    return (a < b) ? a : b;
}

class FileScanner
{
public:
    FileScanner(const std::wstring& targetFile, bool debug = false)
        : m_targetFile(targetFile), m_debug(debug) {}

    ScanResult Scan()
    {
        if (!FileExists(m_targetFile))
        {
            printf("[-] Can't access the target file\n");
            return ScanResult::FileNotFound;
        }

        ScanResult originalFileDetectionStatus = ScanFile(m_targetFile);
        if (originalFileDetectionStatus == ScanResult::NoThreatFound)
        {
            if (m_debug) { printf("Scanning the whole file first\n"); }
            printf("[+] No threat found in submitted file!\n");
            return ScanResult::NoThreatFound;
        }

        if (!CreateTempDirectory())
        {
            printf("[-] C:\\Temp doesn't exist. Creating it...\n");
        }

        std::vector<BYTE> originalFileContents = mReadFile(m_targetFile);
        if (originalFileContents.empty())
        {
            printf("[-] Failed to read target file\n");
            return ScanResult::Error;
        }

        printf("Target file size: %zu bytes\n", originalFileContents.size());
        printf("Analyzing...\n\n");

        int lastGood = 0;
        std::vector<BYTE> splitArray1(originalFileContents.begin(), originalFileContents.begin() + static_cast<int>(std::ceil(originalFileContents.size() / 2.0)));

        while (true)
        {
            if (m_debug) { printf("Testing %zu bytes\n", splitArray1.size()); }

            if (!mWriteFile(m_testFilePath, splitArray1))
            {
                printf("[-] Failed to create test file\n");
                return ScanResult::Error;
            }

            ScanResult detectionStatus = ScanFile(m_testFilePath);
            if (detectionStatus == ScanResult::ThreatFound)
            {
                if (m_debug) { printf("Threat found. Halfsplitting again...\n"); }
                splitArray1 = HalfSplitter(splitArray1, lastGood, originalFileContents);
            }
            else if (detectionStatus == ScanResult::NoThreatFound)
            {
                if (m_debug) { printf("%s", "No threat found. Going up 50% of current size.\n"); }
                lastGood = static_cast<int>(splitArray1.size());
                splitArray1 = Overshot(originalFileContents, static_cast<int>(splitArray1.size()));
            }
            else
            {
                printf("[-] Error occurred during scanning\n");
                return ScanResult::Error;
            }
        }

        return ScanResult::NoThreatFound;
    }

private:
    bool FileExists(const std::wstring& file)
    {
        return GetFileAttributes(file.c_str()) != INVALID_FILE_ATTRIBUTES;
    }

    bool CreateTempDirectory()
    {
        return CreateDirectoryW(L"C:\\Temp", NULL) || GetLastError() == ERROR_ALREADY_EXISTS;
    }

    std::vector<BYTE> mReadFile(const std::wstring& file)
    {
        HANDLE hFile = CreateFile(file.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile == INVALID_HANDLE_VALUE)
        {
            return {};
        }

        DWORD fileSize = GetFileSize(hFile, NULL);
        std::vector<BYTE> fileContents(fileSize);
        DWORD bytesRead;
        ReadFile(hFile, fileContents.data(), fileSize, &bytesRead, NULL);

        CloseHandle(hFile);
        return fileContents;
    }

    bool mWriteFile(const std::wstring& file, const std::vector<BYTE>& data)
    {
        HANDLE hFile = CreateFile(file.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile == INVALID_HANDLE_VALUE)
        {
            return false;
        }

        DWORD bytesWritten;
        WriteFile(hFile, data.data(), static_cast<DWORD>(data.size()), &bytesWritten, NULL);
        CloseHandle(hFile);
        return true;
    }

    ScanResult ScanFile(const std::wstring& file, bool getsig = false)
    {
        std::wstring commandLine = L"C:\\Program Files\\Windows Defender\\MpCmdRun.exe -Scan -ScanType 3 -File \"" + file + L"\" -DisableRemediation -Trace -Level 0x10";
        if (m_debug) { wprintf(L"Debug: Running command: %ls\n", commandLine.c_str()); }

        STARTUPINFOW si = { sizeof(si) };
        PROCESS_INFORMATION pi;

        std::vector<wchar_t> writableCommandLine(commandLine.begin(), commandLine.end());
        writableCommandLine.push_back(0);

        if (!CreateProcessW(NULL, writableCommandLine.data(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
        {
            if (m_debug) { std::cout << "Debug: Failed to create process" << std::endl; }
            return ScanResult::Error;
        }

        if (m_debug) { printf("Debug: Process created with PID: %lu\n", pi.dwProcessId); }

        DWORD waitResult = WaitForSingleObject(pi.hProcess, 30000);
        if (waitResult == WAIT_TIMEOUT)
        {
            if (m_debug) { std::cout << "Debug: Scan timed out" << std::endl; }
            TerminateProcess(pi.hProcess, 1);
            CloseHandle(pi.hProcess);
            CloseHandle(pi.hThread);
            return ScanResult::Timeout;
        }

        if (m_debug) { std::cout << "Debug: Scan process completed" << std::endl; }

        DWORD exitCode;
        GetExitCodeProcess(pi.hProcess, &exitCode);
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);

        if (m_debug) { printf("Debug: Exit code: %lu\n", exitCode); }

        switch (exitCode)
        {
        case 0:
            return ScanResult::NoThreatFound;
        case 2:
            return ScanResult::ThreatFound;
        default:
            return ScanResult::Error;
        }
    }

    std::wstring FindSectionByOffset(DWORD offset)
    {
        HANDLE hFile = CreateFile(m_targetFile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile == INVALID_HANDLE_VALUE)
        {
            printf("[-] Error opening file for reading\n");
            return L"";
        }

        IMAGE_DOS_HEADER dosHeader;
        DWORD bytesRead;
        ReadFile(hFile, &dosHeader, sizeof(dosHeader), &bytesRead, NULL);

        if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE)
        {
            printf("[-] Not a valid DOS executable\n");
            CloseHandle(hFile);
            return L"";
        }

        SetFilePointer(hFile, dosHeader.e_lfanew, NULL, FILE_BEGIN);

        IMAGE_NT_HEADERS ntHeaders;
        ReadFile(hFile, &ntHeaders, sizeof(ntHeaders), &bytesRead, NULL);

        if (ntHeaders.Signature != IMAGE_NT_SIGNATURE)
        {
            printf("[-] Not a valid NT executable\n");
            CloseHandle(hFile);
            return L"";
        }

        DWORD sectionLocation = dosHeader.e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + ntHeaders.FileHeader.SizeOfOptionalHeader;
        DWORD sectionSize = sizeof(IMAGE_SECTION_HEADER);

        for (int i = 0; i < ntHeaders.FileHeader.NumberOfSections; ++i)
        {
            IMAGE_SECTION_HEADER sectionHeader;
            SetFilePointer(hFile, sectionLocation + (sectionSize * i), NULL, FILE_BEGIN);
            ReadFile(hFile, &sectionHeader, sizeof(sectionHeader), &bytesRead, NULL);

            if (offset >= sectionHeader.PointerToRawData && offset < sectionHeader.PointerToRawData + sectionHeader.SizeOfRawData)
            {
                std::wstring sectionName(sectionHeader.Name, sectionHeader.Name + strnlen_s((const char*)sectionHeader.Name, IMAGE_SIZEOF_SHORT_NAME));
                CloseHandle(hFile);
                return sectionName;
            }
        }

        CloseHandle(hFile);
        return L"Not found"; // Смещение не принадлежит ни одной из секций
    }

    std::vector<BYTE> HalfSplitter(const std::vector<BYTE>& originalArray, int lastGood, const std::vector<BYTE>& pe)
    {
        std::vector<BYTE> splitArray(originalArray.begin(), originalArray.begin() + (lastGood + originalArray.size()) / 2);

        if (originalArray.size() == splitArray.size() + 1)
        {
            printf("[!] Identified end of bad bytes at offset 0x%X in the original file\n", static_cast<int>(originalArray.size()));
            std::wstring sectionName = FindSectionByOffset(static_cast<DWORD>(originalArray.size()));
            wprintf(L"[!] The bad bytes are in the section: %s\n", sectionName.c_str());

            ScanFile(m_testFilePath, true);
            std::vector<BYTE> offendingBytes(my_own_min(originalArray.size(), static_cast<size_t>(256)));
            std::copy(originalArray.end() - offendingBytes.size(), originalArray.end(), offendingBytes.begin());

            size_t startIndex = lastGood;
            size_t endIndex = originalArray.size();
            size_t bufferSize = endIndex - startIndex;
            size_t offendingBytesLength = my_own_min(bufferSize, static_cast<size_t>(256));
            size_t startingAddress = endIndex - offendingBytesLength;

            DisassembleCode(offendingBytes, offendingBytesLength, startingAddress);

            HexDump(offendingBytes, 16);
            DeleteFile(m_testFilePath.c_str());
            exit(0);
        }
        return splitArray;
    }

    std::vector<BYTE> Overshot(const std::vector<BYTE>& originalArray, int splitArraySize)
    {
        int newSize = (originalArray.size() - splitArraySize) / 2 + splitArraySize;
        if (newSize == originalArray.size() - 1)
        {
            printf("Exhausted the search. The binary looks good to go!\n");
            exit(0);
        }
        return std::vector<BYTE>(originalArray.begin(), originalArray.begin() + newSize);
    }

    bool Is64BitPE(const std::wstring& filePath)
    {
        HANDLE hFile = CreateFile(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hFile == INVALID_HANDLE_VALUE)
        {
            printf("[-] Error opening file for reading\n");
            return false;
        }

        IMAGE_DOS_HEADER dosHeader;
        DWORD bytesRead;
        ReadFile(hFile, &dosHeader, sizeof(dosHeader), &bytesRead, NULL);

        if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE)
        {
            printf("[-] Not a valid DOS executable\n");
            CloseHandle(hFile);
            return false;
        }

        SetFilePointer(hFile, dosHeader.e_lfanew, NULL, FILE_BEGIN);

        IMAGE_NT_HEADERS32 ntHeader32;
        ReadFile(hFile, &ntHeader32, sizeof(ntHeader32), &bytesRead, NULL);

        CloseHandle(hFile);

        if (ntHeader32.Signature != IMAGE_NT_SIGNATURE)
        {
            printf("[-] Not a valid NT executable\n");
            return false;
        }

        return (ntHeader32.FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64 ||
            ntHeader32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64);
    }

    void DisassembleCode(const std::vector<BYTE>& code, size_t codeSize, size_t startingAddress)
    {
        csh handle;
        cs_mode mode;

        // Determine architecture mode
        if (Is64BitPE(m_targetFile))
            mode = CS_MODE_64;
        else
            mode = CS_MODE_32;

        if (cs_open(CS_ARCH_X86, mode, &handle) != CS_ERR_OK)
        {
            printf("[-] Failed to initialize Capstone\n");
            return;
        }

        cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
        cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);

        cs_insn* insn;
        size_t count = cs_disasm(handle, code.data(), codeSize, startingAddress, 0, &insn);

        if (count > 0)
        {
            printf("Disassembled instructions:\n");
            for (size_t i = 0; i < count; i++)
            {
                printf("0x%llX ", insn[i].address);
                for (size_t j = 0; j < insn[i].size; j++)
                {
                    printf("%02X ", insn[i].bytes[j]);
                }
                printf("%-10s %s\n", insn[i].mnemonic, insn[i].op_str);
            }
            cs_free(insn, count);
        }

        cs_close(&handle);
    }


    void HexDump(const std::vector<BYTE>& bytes, int bytesPerLine)
    {
        if (bytes.empty())
        {
            printf("[-] Empty array supplied. Something is wrong...\n");
            return;
        }

        int bytesLength = static_cast<int>(bytes.size());

        const char* HexChars = "0123456789ABCDEF";

        int firstHexColumn = 8 + 3;

        int firstCharColumn = firstHexColumn + bytesPerLine * 3 + (bytesPerLine - 1) / 8 + 2;

        int lineLength = firstCharColumn + bytesPerLine + 2;

        std::vector<char> line(lineLength, ' ');
        line[lineLength - 2] = '\r';
        line[lineLength - 1] = '\n';

        int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine;
        std::string result;
        result.reserve(expectedLines * lineLength);

        for (int i = 0; i < bytesLength; i += bytesPerLine)
        {
            line[0] = HexChars[(i >> 28) & 0xF];
            line[1] = HexChars[(i >> 24) & 0xF];
            line[2] = HexChars[(i >> 20) & 0xF];
            line[3] = HexChars[(i >> 16) & 0xF];
            line[4] = HexChars[(i >> 12) & 0xF];
            line[5] = HexChars[(i >> 8) & 0xF];
            line[6] = HexChars[(i >> 4) & 0xF];
            line[7] = HexChars[(i >> 0) & 0xF];

            int hexColumn = firstHexColumn;
            int charColumn = firstCharColumn;

            for (int j = 0; j < bytesPerLine; j++)
            {
                if (j > 0 && (j & 7) == 0) hexColumn++;
                if (i + j >= bytesLength)
                {
                    line[hexColumn] = ' ';
                    line[hexColumn + 1] = ' ';
                    line[charColumn] = ' ';
                }
                else
                {
                    BYTE b = bytes[i + j];
                    line[hexColumn] = HexChars[(b >> 4) & 0xF];
                    line[hexColumn + 1] = HexChars[b & 0xF];
                    line[charColumn] = (b < 32 ? '·' : static_cast<char>(b));
                }
                hexColumn += 3;
                charColumn++;
            }
            result.append(line.begin(), line.end());
        }
        printf("%s", result.c_str());
    }

    std::wstring m_targetFile;
    std::wstring m_testFilePath = L"C:\\Temp\\testfile.exe";
    bool m_debug;
};

int wmain(int argc, wchar_t* argv[])
{
    if (argc < 2)
    {
        printf("Usage: DefenderCheck.exe [path/to/file]\n");
        return 1;
    }

    bool debug = (argc == 3 && std::wstring(argv[2]).find(L"debug") != std::wstring::npos);
    std::wstring targetFile = argv[1];

    FileScanner scanner(targetFile, debug);
    ScanResult result = scanner.Scan();

    return static_cast<int>(result);
}
 
Последнее редактирование:


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх