zoukankan      html  css  js  c++  java
  • 3.资源里加个混淆

    目录

    1.简单的混淆代码

    2.恶意软件资源中释放混淆资源

    3.逆向分析

    4.参考

    简单的混淆代码

    在恶意软件分析中,混淆是经常使用的一种手段。恶意软件通过对数据进行混淆,不但给杀毒软件的检测和查杀带来一定的困难,也会给逆向分析者带来一定的阻碍。这里就抛出一个非常简单的砖来说说混淆。我这里简单的写了一个程序,输入想要混淆的文件名就会在同目录下生成名为shellcode的混淆文件。这里混淆过程其实也非常简单,就是对文件进行读写异或等操作

     1 #include<Windows.h>
     2 #include<stdio.h>
     3 #include<tchar.h>
     4 
     5 void __cdecl _tmain(int argc, TCHAR *argv[])
     6 {
     7     HANDLE hFiler;
     8     HANDLE hFilew;
     9     BOOL ifFilesize = FALSE;
    10     BOOL bErrorFlag = FALSE;
    11     BOOL Flag = FALSE;
    12     DWORD buffertoread;
    13     DWORD dwByteWrite = 0;
    14     LPVOID lpAddress;
    15     LARGE_INTEGER FileSize;
    16 
    17     //获取文件句柄
    18     hFiler = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    19     if (hFiler == INVALID_HANDLE_VALUE)
    20     {
    21         printf("Unable to open file!");
    22         return;
    23     }
    24     //获取文件大小
    25     ifFilesize = GetFileSizeEx(hFiler, &FileSize);
    26     if (ifFilesize == FALSE)
    27     {
    28         printf("%d", GetLastError());
    29     }
    30     else
    31     {
    32         printf("%lld", FileSize.QuadPart);
    33     }
    34 
    35     //分配一块内存
    36     lpAddress = VirtualAlloc(NULL, (SIZE_T)FileSize.QuadPart, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
    37     if (lpAddress == NULL)
    38     {
    39         printf("LocalAlloc failed!");
    40         return;
    41     }
    42 
    43     //读取文件
    44     bErrorFlag = ReadFile(hFiler, lpAddress, (DWORD)FileSize.QuadPart, &buffertoread, NULL);
    45     if (bErrorFlag == FALSE)
    46     {
    47         printf("Readfile false:%d", GetLastError());
    48         return;
    49     }
    50 
    51     //对数据进行异或,最简单的混淆,可以修改这里来实现更加复杂的混淆
    52     BYTE *point = lpAddress;
    53     for (int i = 0; i < (int)FileSize.QuadPart; i++)
    54     {
    55         (*point) ^= 0x99;
    56         point++;
    57     }
    58 
    59     //在同目录下生成一个名为shellcode的文件
    60     hFilew = CreateFile(L"shellcode", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
    61     if (hFilew == INVALID_HANDLE_VALUE)
    62     {
    63         printf("Unable to open file");
    64     }
    65 
    66     //写入混淆后的内容
    67     Flag = WriteFile(hFilew, lpAddress, (DWORD)FileSize.QuadPart, &dwByteWrite, NULL);
    68     if (Flag == FALSE)
    69     {
    70         printf("Fail to WriteFile");
    71     }
    72 
    73     return;
    74 }

    恶意软件资源中释放混淆代码

    上面说到的是混淆的过程,这里就是恶意软件对资源混淆后是如何进行释放的。这里释放资源和第二课释放资源类似,不过由于资源混淆了,所以多了一步解密资源的过程。由于资源在PE中为只读数据,所以获取到指向资源的指针后不能像第二课那样直接进行解密,需要复制到内存中再进行解密。还有就是我们之前加混淆是异或0x99,所以解密也是通过异或0x99(这里可以不懂可以看一下关于异或的知识)。

     1 #include<Windows.h>
     2 #include<stdio.h>
     3 
     4 #include"resource.h"    //要包含资源文件的头文件
     5 
     6 int main()
     7 {
     8     HRSRC Shellcode;
     9     HGLOBAL Loadshellcode;
    10     HANDLE hFile;
    11     DWORD ShellcodeSize;
    12     DWORD dwByteWrite = 0;
    13     LPVOID Lockshellcode;
    14     LPVOID lpAddress;
    15     BOOL Flag = FALSE;
    16 
    17     //找到资源
    18     Shellcode = FindResource(NULL, MAKEINTRESOURCE(IDR_SHELLCODE1), TEXT("Shellcode"));
    19     if (Shellcode == NULL)
    20     {
    21         printf("Could not locate dialog box.");
    22         return 0;
    23     }
    24 
    25     //加载资源
    26     Loadshellcode = LoadResource(NULL, Shellcode);
    27     if (Loadshellcode == NULL)
    28     {
    29         printf("Could not lock dialog box.");
    30         return 0;
    31     }
    32 
    33     //获取指向资源的指针
    34     Lockshellcode = LockResource(Loadshellcode);
    35     if (Lockshellcode == NULL)
    36     {
    37         printf("Could not lock dialog box.");
    38         return 0;
    39     }
    40 
    41     //获取资源大小,用于下面写文件
    42     ShellcodeSize = SizeofResource(NULL, Shellcode);
    43 
    44     //资源处为只读数据不能直接进行解密,需要复制到内存空间中才可以进行解密
    45     lpAddress = VirtualAlloc(NULL, (SIZE_T)ShellcodeSize, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE);
    46     if (lpAddress == NULL)
    47     {
    48     printf("LocalAlloc failed!");
    49     return 0;
    50     }
    51 
    52     //复制资源到内存空间
    53     memcpy(lpAddress, Lockshellcode, (size_t)ShellcodeSize);
    54 
    55     //解密出shellcode
    56     byte *point = lpAddress;
    57     for (int i = 0; i < (int)ShellcodeSize; i++)
    58     {
    59         (*point) ^= 0x99;
    60         point++;
    61     }
    62 
    63     //创建文件
    64     hFile = CreateFile(L"PE", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
    65     if (hFile == INVALID_HANDLE_VALUE)
    66     {
    67         printf("Unable to open file");
    68     }
    69 
    70     //写入文件
    71     Flag = WriteFile(hFile, lpAddress, ShellcodeSize, &dwByteWrite, NULL);
    72     if (Flag == FALSE)
    73     {
    74         printf("Fail to WriteFile");
    75     }
    76 
    77     return 0;
    78 }

     

     逆向分析

    逆向分析时,如果资源经过混淆,我们用resourse hacker提取出来是混淆后的数据,如果再写一个解密程序进行解密是非常耗时间的(可以通过逆向恶意程序解密资源的过程来编写解密程序)。由于恶意程序最终需要的也是解密后的数据,所以我们可以通过OD跟踪恶意程序解密出资源数据后,再转存解密后的数据。如何确定那个地方是数据解密后呢?我们从上面释放资源的程序中看出,由于需要解密一块数据,所以会进入一个循环对数据进行解密。当循环结束时,我们就可以认为数据解密完成。在平时的恶意软件分析中,数据解密也会进入循环中,有经验的逆向分析者可能一眼就看出数据解密的地方。对初学者来说多分析多调试,也会很快会找到其中的规律

     

    参考

    文件读写:https://docs.microsoft.com/zh-cn/windows/desktop/FileIO/opening-a-file-for-reading-or-writing

    获取文件大小:https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfilesize

    内存操作:https://docs.microsoft.com/zh-cn/windows/desktop/Memory/reserving-and-committing-memory

  • 相关阅读:
    NYOJ127 星际之门(一)【定理】
    JAVAWEB开发之JSTL标签库的使用、 自己定义EL函数、自己定义标签(带属性的、带标签体的)
    如何写一个不可变类
    保护性拷贝
    猴子搬香蕉问题
    阿里云服务器安装redis启动失败问题排查
    oauth2测试
    远程连接云服务器上的mysql失败问题解决
    SQLServer中将yyyy:MM:dd HH:mm:ss.sss转为yyyyMMddHHmmss
    Centos8 安装 MySQL
  • 原文地址:https://www.cnblogs.com/QKSword/p/10549784.html
Copyright © 2011-2022 走看看