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

猜你喜欢

转载自www.cnblogs.com/QKSword/p/10549784.html
3.